
<!DOCTYPE html>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<title>provider: Go Coverage Report</title>
		<style>
			body {
				background: black;
				color: rgb(80, 80, 80);
			}
			body, pre, #legend span {
				font-family: Menlo, monospace;
				font-weight: bold;
			}
			#topbar {
				background: black;
				position: fixed;
				top: 0; left: 0; right: 0;
				height: 42px;
				border-bottom: 1px solid rgb(80, 80, 80);
			}
			#content {
				margin-top: 50px;
			}
			#nav, #legend {
				float: left;
				margin-left: 10px;
			}
			#legend {
				margin-top: 12px;
			}
			#nav {
				margin-top: 10px;
			}
			#legend span {
				margin: 0 5px;
			}
			.cov0 { color: rgb(192, 0, 0) }
.cov1 { color: rgb(128, 128, 128) }
.cov2 { color: rgb(116, 140, 131) }
.cov3 { color: rgb(104, 152, 134) }
.cov4 { color: rgb(92, 164, 137) }
.cov5 { color: rgb(80, 176, 140) }
.cov6 { color: rgb(68, 188, 143) }
.cov7 { color: rgb(56, 200, 146) }
.cov8 { color: rgb(44, 212, 149) }
.cov9 { color: rgb(32, 224, 152) }
.cov10 { color: rgb(20, 236, 155) }

		</style>
	</head>
	<body>
		<div id="topbar">
			<div id="nav">
				<select id="files">
				
				<option value="file0">github.com/GoSimplicity/AI-CloudOps/internal/tree/provider/aliyun_provider.go (0.0%)</option>
				
				<option value="file1">github.com/GoSimplicity/AI-CloudOps/internal/tree/provider/factory.go (0.0%)</option>
				
				<option value="file2">github.com/GoSimplicity/AI-CloudOps/internal/tree/provider/huawei_provider.go (14.1%)</option>
				
				</select>
			</div>
			<div id="legend">
				<span>not tracked</span>
			
				<span class="cov0">not covered</span>
				<span class="cov8">covered</span>
			
			</div>
		</div>
		<div id="content">
		
		<pre class="file" id="file0" style="display: none">/*
 * MIT License
 *
 * Copyright (c) 2024 Bamboo
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

package provider

import (
        "context"
        "fmt"
        "os"
        "time"

        "github.com/GoSimplicity/AI-CloudOps/internal/model"
        "github.com/GoSimplicity/AI-CloudOps/pkg/aliyun"
        ecs "github.com/alibabacloud-go/ecs-20140526/v2/client"
        "github.com/alibabacloud-go/tea/tea"
        vpc "github.com/alibabacloud-go/vpc-20160428/v2/client"
        "go.uber.org/zap"
)

type AliyunProviderImpl struct {
        logger               *zap.Logger
        sdk                  *aliyun.SDK
        ecsService           *aliyun.EcsService
        vpcService           *aliyun.VpcService
        diskService          *aliyun.DiskService
        securityGroupService *aliyun.SecurityGroupService
}

func NewAliyunProvider(logger *zap.Logger) *AliyunProviderImpl <span class="cov0" title="0">{
        accessKeyId := os.Getenv("ALIYUN_ACCESS_KEY_ID")
        accessKeySecret := os.Getenv("ALIYUN_ACCESS_KEY_SECRET")

        // 检查必要的环境变量
        if accessKeyId == "" || accessKeySecret == "" </span><span class="cov0" title="0">{
                logger.Error("ALIYUN_ACCESS_KEY_ID and ALIYUN_ACCESS_KEY_SECRET environment variables are required")
                return nil
        }</span>

        <span class="cov0" title="0">sdk := aliyun.NewSDK(logger, accessKeyId, accessKeySecret)

        return &amp;AliyunProviderImpl{
                logger:               logger,
                sdk:                  sdk,
                ecsService:           aliyun.NewEcsService(sdk),
                vpcService:           aliyun.NewVpcService(sdk),
                diskService:          aliyun.NewDiskService(sdk),
                securityGroupService: aliyun.NewSecurityGroupService(sdk),
        }</span>
}

// 基础服务
func (a *AliyunProviderImpl) SyncResources(ctx context.Context, region string) error <span class="cov0" title="0">{
        if region == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region cannot be empty")
        }</span>

        <span class="cov0" title="0">a.logger.Info("starting resource sync", zap.String("region", region))

        // TODO: 实现具体的资源同步逻辑
        // 可以包括同步ECS实例、VPC、安全组等资源

        a.logger.Info("resource sync completed", zap.String("region", region))
        return nil</span>
}

func (a *AliyunProviderImpl) ListRegions(ctx context.Context) ([]*model.RegionResp, error) <span class="cov0" title="0">{
        regions, err := a.ecsService.ListRegions(ctx)
        if err != nil </span><span class="cov0" title="0">{
                a.logger.Error("failed to list regions", zap.Error(err))
                return nil, fmt.Errorf("list regions failed: %w", err)
        }</span>

        <span class="cov0" title="0">if len(regions) == 0 </span><span class="cov0" title="0">{
                return []*model.RegionResp{}, nil
        }</span>

        <span class="cov0" title="0">result := make([]*model.RegionResp, 0, len(regions))
        for _, region := range regions </span><span class="cov0" title="0">{
                if region == nil </span><span class="cov0" title="0">{
                        continue</span>
                }
                <span class="cov0" title="0">result = append(result, &amp;model.RegionResp{
                        RegionId:       tea.StringValue(region.RegionId),
                        LocalName:      tea.StringValue(region.LocalName),
                        RegionEndpoint: tea.StringValue(region.RegionEndpoint),
                })</span>
        }

        <span class="cov0" title="0">return result, nil</span>
}

func (a *AliyunProviderImpl) GetZonesByVpc(ctx context.Context, region string, vpcId string) ([]*model.ZoneResp, error) <span class="cov0" title="0">{
        if region == "" || vpcId == "" </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("region and vpcId cannot be empty")
        }</span>

        <span class="cov0" title="0">zones, _, err := a.vpcService.GetZonesByVpc(ctx, region, vpcId)
        if err != nil </span><span class="cov0" title="0">{
                a.logger.Error("failed to get zones by VPC", zap.Error(err), zap.String("vpcId", vpcId))
                return nil, fmt.Errorf("get zones by VPC failed: %w", err)
        }</span>

        <span class="cov0" title="0">if len(zones) == 0 </span><span class="cov0" title="0">{
                return nil, nil
        }</span>

        <span class="cov0" title="0">result := make([]*model.ZoneResp, 0, len(zones))
        for _, zone := range zones </span><span class="cov0" title="0">{
                if zone == nil </span><span class="cov0" title="0">{
                        continue</span>
                }
                <span class="cov0" title="0">result = append(result, &amp;model.ZoneResp{
                        ZoneId:    tea.StringValue(zone.ZoneId),
                        LocalName: tea.StringValue(zone.LocalName),
                })</span>
        }

        <span class="cov0" title="0">return result, nil</span>
}

// ECS实例管理
func (a *AliyunProviderImpl) ListInstances(ctx context.Context, region string, page, size int) ([]*model.ResourceEcs, int64, error) <span class="cov0" title="0">{
        if region == "" </span><span class="cov0" title="0">{
                return nil, 0, fmt.Errorf("region cannot be empty")
        }</span>
        <span class="cov0" title="0">if page &lt;= 0 || size &lt;= 0 </span><span class="cov0" title="0">{
                return nil, 0, fmt.Errorf("page and size must be positive integers")
        }</span>

        <span class="cov0" title="0">req := &amp;aliyun.ListInstancesRequest{
                Region: region,
                Page:   page,
                Size:   size,
        }

        resp, err := a.ecsService.ListInstances(ctx, req)
        if err != nil </span><span class="cov0" title="0">{
                a.logger.Error("failed to list instances", zap.Error(err), zap.String("region", region))
                return nil, 0, fmt.Errorf("list instances failed: %w", err)
        }</span>

        <span class="cov0" title="0">if resp == nil || len(resp.Instances) == 0 </span><span class="cov0" title="0">{
                return nil, 0, nil
        }</span>

        <span class="cov0" title="0">result := make([]*model.ResourceEcs, 0, len(resp.Instances))
        for _, instance := range resp.Instances </span><span class="cov0" title="0">{
                if instance == nil </span><span class="cov0" title="0">{
                        continue</span>
                }
                <span class="cov0" title="0">result = append(result, a.convertToResourceEcsFromListInstance(instance))</span>
        }

        <span class="cov0" title="0">return result, resp.Total, nil</span>
}

func (a *AliyunProviderImpl) GetInstance(ctx context.Context, region string, instanceID string) (*model.ResourceEcs, error) <span class="cov0" title="0">{
        if region == "" || instanceID == "" </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("region and instanceID cannot be empty")
        }</span>

        <span class="cov0" title="0">instance, err := a.ecsService.GetInstanceDetail(ctx, region, instanceID)
        if err != nil </span><span class="cov0" title="0">{
                a.logger.Error("failed to get instance detail", zap.Error(err), zap.String("instanceID", instanceID))
                return nil, fmt.Errorf("get instance detail failed: %w", err)
        }</span>

        <span class="cov0" title="0">if instance == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("instance not found")
        }</span>

        <span class="cov0" title="0">return a.convertToResourceEcsFromInstanceDetail(instance), nil</span>
}

func (a *AliyunProviderImpl) CreateInstance(ctx context.Context, region string, config *model.CreateEcsResourceReq) error <span class="cov0" title="0">{
        if region == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region cannot be empty")
        }</span>
        <span class="cov0" title="0">if config == nil </span><span class="cov0" title="0">{
                return fmt.Errorf("config cannot be nil")
        }</span>

        <span class="cov0" title="0">req := &amp;aliyun.CreateInstanceRequest{
                Region:             region,
                ZoneId:             config.ZoneId,
                ImageId:            config.ImageId,
                InstanceType:       config.InstanceType,
                SecurityGroupIds:   config.SecurityGroupIds,
                VSwitchId:          config.VSwitchId,
                InstanceName:       config.InstanceName,
                Hostname:           config.Hostname,
                Password:           config.Password,
                Description:        config.Description,
                Amount:             config.Amount,
                DryRun:             config.DryRun,
                InstanceChargeType: string(config.InstanceChargeType),
                SystemDiskCategory: config.SystemDiskCategory,
                SystemDiskSize:     config.SystemDiskSize,
                DataDiskCategory:   config.DataDiskCategory,
                DataDiskSize:       config.DataDiskSize,
        }

        _, err := a.ecsService.CreateInstance(ctx, req)
        if err != nil </span><span class="cov0" title="0">{
                a.logger.Error("failed to create instance", zap.Error(err), zap.String("region", region))
                return fmt.Errorf("create instance failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

func (a *AliyunProviderImpl) DeleteInstance(ctx context.Context, region string, instanceID string) error <span class="cov0" title="0">{
        if region == "" || instanceID == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region and instanceID cannot be empty")
        }</span>

        <span class="cov0" title="0">err := a.ecsService.DeleteInstance(ctx, region, instanceID, true)
        if err != nil </span><span class="cov0" title="0">{
                a.logger.Error("failed to delete instance", zap.Error(err), zap.String("instanceID", instanceID))
                return fmt.Errorf("delete instance failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

func (a *AliyunProviderImpl) StartInstance(ctx context.Context, region string, instanceID string) error <span class="cov0" title="0">{
        if region == "" || instanceID == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region and instanceID cannot be empty")
        }</span>

        <span class="cov0" title="0">err := a.ecsService.StartInstance(ctx, region, instanceID)
        if err != nil </span><span class="cov0" title="0">{
                a.logger.Error("failed to start instance", zap.Error(err), zap.String("instanceID", instanceID))
                return fmt.Errorf("start instance failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

func (a *AliyunProviderImpl) StopInstance(ctx context.Context, region string, instanceID string) error <span class="cov0" title="0">{
        if region == "" || instanceID == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region and instanceID cannot be empty")
        }</span>

        <span class="cov0" title="0">err := a.ecsService.StopInstance(ctx, region, instanceID, false)
        if err != nil </span><span class="cov0" title="0">{
                a.logger.Error("failed to stop instance", zap.Error(err), zap.String("instanceID", instanceID))
                return fmt.Errorf("stop instance failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

func (a *AliyunProviderImpl) RestartInstance(ctx context.Context, region string, instanceID string) error <span class="cov0" title="0">{
        if region == "" || instanceID == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region and instanceID cannot be empty")
        }</span>

        <span class="cov0" title="0">err := a.ecsService.RestartInstance(ctx, region, instanceID)
        if err != nil </span><span class="cov0" title="0">{
                a.logger.Error("failed to restart instance", zap.Error(err), zap.String("instanceID", instanceID))
                return fmt.Errorf("restart instance failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

// VPC网络管理
func (a *AliyunProviderImpl) ListVPCs(ctx context.Context, region string, pageNumber, pageSize int) ([]*model.ResourceVpc, error) <span class="cov0" title="0">{
        if region == "" </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("region cannot be empty")
        }</span>
        <span class="cov0" title="0">if pageNumber &lt;= 0 || pageSize &lt;= 0 </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("pageNumber and pageSize must be positive integers")
        }</span>

        <span class="cov0" title="0">req := &amp;aliyun.ListVpcsRequest{
                Region: region,
                Page:   pageNumber,
                Size:   pageSize,
        }

        resp, err := a.vpcService.ListVpcs(ctx, req)
        if err != nil </span><span class="cov0" title="0">{
                a.logger.Error("failed to list VPCs", zap.Error(err), zap.String("region", region))
                return nil, fmt.Errorf("list VPCs failed: %w", err)
        }</span>

        <span class="cov0" title="0">if resp == nil || len(resp.Vpcs) == 0 </span><span class="cov0" title="0">{
                return nil, nil
        }</span>

        <span class="cov0" title="0">result := make([]*model.ResourceVpc, 0, len(resp.Vpcs))
        for _, vpcData := range resp.Vpcs </span><span class="cov0" title="0">{
                if vpcData == nil </span><span class="cov0" title="0">{
                        continue</span>
                }
                <span class="cov0" title="0">result = append(result, a.convertToResourceVpcFromListVpc(vpcData, region))</span>
        }

        <span class="cov0" title="0">return result, nil</span>
}

func (a *AliyunProviderImpl) GetVPC(ctx context.Context, region string, vpcID string) (*model.ResourceVpc, error) <span class="cov0" title="0">{
        if region == "" || vpcID == "" </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("region and vpcID cannot be empty")
        }</span>

        <span class="cov0" title="0">vpcDetail, err := a.vpcService.GetVpcDetail(ctx, region, vpcID)
        if err != nil </span><span class="cov0" title="0">{
                a.logger.Error("failed to get VPC detail", zap.Error(err), zap.String("vpcID", vpcID))
                return nil, fmt.Errorf("get VPC detail failed: %w", err)
        }</span>

        <span class="cov0" title="0">if vpcDetail == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("VPC not found")
        }</span>

        <span class="cov0" title="0">return a.convertToResourceVpcFromDetail(vpcDetail, region), nil</span>
}

func (a *AliyunProviderImpl) CreateVPC(ctx context.Context, region string, config *model.CreateVpcResourceReq) error <span class="cov0" title="0">{
        if region == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region cannot be empty")
        }</span>
        <span class="cov0" title="0">if config == nil </span><span class="cov0" title="0">{
                return fmt.Errorf("config cannot be nil")
        }</span>

        <span class="cov0" title="0">req := &amp;aliyun.CreateVpcRequest{
                Region:           region,
                VpcName:          config.VpcName,
                CidrBlock:        config.CidrBlock,
                Description:      config.Description,
                ZoneId:           config.ZoneId,
                VSwitchName:      config.VSwitchName,
                VSwitchCidrBlock: config.VSwitchCidrBlock,
        }

        _, err := a.vpcService.CreateVPC(ctx, req)
        if err != nil </span><span class="cov0" title="0">{
                a.logger.Error("failed to create VPC", zap.Error(err), zap.String("region", region))
                return fmt.Errorf("create VPC failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

func (a *AliyunProviderImpl) DeleteVPC(ctx context.Context, region string, vpcID string) error <span class="cov0" title="0">{
        if region == "" || vpcID == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region and vpcID cannot be empty")
        }</span>

        <span class="cov0" title="0">err := a.vpcService.DeleteVPC(ctx, region, vpcID)
        if err != nil </span><span class="cov0" title="0">{
                a.logger.Error("failed to delete VPC", zap.Error(err), zap.String("vpcID", vpcID))
                return fmt.Errorf("delete VPC failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

// 安全组管理
func (a *AliyunProviderImpl) ListSecurityGroups(ctx context.Context, region string, pageNumber, pageSize int) ([]*model.ResourceSecurityGroup, error) <span class="cov0" title="0">{
        if region == "" </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("region cannot be empty")
        }</span>
        <span class="cov0" title="0">if pageNumber &lt;= 0 || pageSize &lt;= 0 </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("pageNumber and pageSize must be positive integers")
        }</span>

        <span class="cov0" title="0">req := &amp;aliyun.ListSecurityGroupsRequest{
                Region:     region,
                PageNumber: pageNumber,
                PageSize:   pageSize,
        }

        resp, err := a.securityGroupService.ListSecurityGroups(ctx, req)
        if err != nil </span><span class="cov0" title="0">{
                a.logger.Error("failed to list security groups", zap.Error(err), zap.String("region", region))
                return nil, fmt.Errorf("list security groups failed: %w", err)
        }</span>

        <span class="cov0" title="0">if resp == nil || len(resp.SecurityGroups) == 0 </span><span class="cov0" title="0">{
                return nil, nil
        }</span>

        <span class="cov0" title="0">result := make([]*model.ResourceSecurityGroup, 0, len(resp.SecurityGroups))
        for _, sg := range resp.SecurityGroups </span><span class="cov0" title="0">{
                if sg == nil </span><span class="cov0" title="0">{
                        continue</span>
                }
                <span class="cov0" title="0">result = append(result, a.convertToResourceSecurityGroupFromList(sg, region))</span>
        }

        <span class="cov0" title="0">return result, nil</span>
}

func (a *AliyunProviderImpl) GetSecurityGroup(ctx context.Context, region string, securityGroupID string) (*model.ResourceSecurityGroup, error) <span class="cov0" title="0">{
        if region == "" || securityGroupID == "" </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("region and securityGroupID cannot be empty")
        }</span>

        <span class="cov0" title="0">sg, err := a.securityGroupService.GetSecurityGroupDetail(ctx, region, securityGroupID)
        if err != nil </span><span class="cov0" title="0">{
                a.logger.Error("failed to get security group detail", zap.Error(err), zap.String("securityGroupID", securityGroupID))
                return nil, fmt.Errorf("get security group detail failed: %w", err)
        }</span>

        <span class="cov0" title="0">if sg == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("security group not found")
        }</span>

        <span class="cov0" title="0">return a.convertToResourceSecurityGroupFromDetail(sg, region), nil</span>
}

func (a *AliyunProviderImpl) CreateSecurityGroup(ctx context.Context, region string, config *model.CreateSecurityGroupReq) error <span class="cov0" title="0">{
        if region == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region cannot be empty")
        }</span>
        <span class="cov0" title="0">if config == nil </span><span class="cov0" title="0">{
                return fmt.Errorf("config cannot be nil")
        }</span>

        <span class="cov0" title="0">req := &amp;aliyun.CreateSecurityGroupRequest{
                Region:            region,
                SecurityGroupName: config.SecurityGroupName,
                Description:       config.Description,
                VpcId:             config.VpcId,
                SecurityGroupType: config.SecurityGroupType,
                ResourceGroupId:   config.ResourceGroupId,
                Tags:              config.Tags,
        }

        _, err := a.securityGroupService.CreateSecurityGroup(ctx, req)
        if err != nil </span><span class="cov0" title="0">{
                a.logger.Error("failed to create security group", zap.Error(err), zap.String("region", region))
                return fmt.Errorf("create security group failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

func (a *AliyunProviderImpl) DeleteSecurityGroup(ctx context.Context, region string, securityGroupID string) error <span class="cov0" title="0">{
        if region == "" || securityGroupID == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region and securityGroupID cannot be empty")
        }</span>

        <span class="cov0" title="0">err := a.securityGroupService.DeleteSecurityGroup(ctx, region, securityGroupID)
        if err != nil </span><span class="cov0" title="0">{
                a.logger.Error("failed to delete security group", zap.Error(err), zap.String("securityGroupID", securityGroupID))
                return fmt.Errorf("delete security group failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

// 磁盘管理 - 需要修改以符合新接口
func (a *AliyunProviderImpl) ListDisks(ctx context.Context, region string, pageNumber, pageSize int) ([]*model.ResourceDisk, error) <span class="cov0" title="0">{
        if region == "" </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("region cannot be empty")
        }</span>
        <span class="cov0" title="0">if pageNumber &lt;= 0 || pageSize &lt;= 0 </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("pageNumber and pageSize must be positive integers")
        }</span>

        <span class="cov0" title="0">req := &amp;aliyun.ListDisksRequest{
                Region: region,
                Page:   pageNumber,
                Size:   pageSize,
        }

        resp, err := a.diskService.ListDisks(ctx, req)
        if err != nil </span><span class="cov0" title="0">{
                a.logger.Error("failed to list disks", zap.Error(err), zap.String("region", region))
                return nil, fmt.Errorf("list disks failed: %w", err)
        }</span>

        <span class="cov0" title="0">if resp == nil || len(resp.Disks) == 0 </span><span class="cov0" title="0">{
                return nil, nil
        }</span>

        <span class="cov0" title="0">result := make([]*model.ResourceDisk, 0, len(resp.Disks))
        for _, disk := range resp.Disks </span><span class="cov0" title="0">{
                if disk == nil </span><span class="cov0" title="0">{
                        continue</span>
                }
                <span class="cov0" title="0">result = append(result, a.convertToResourceDiskFromList(disk, region))</span>
        }

        <span class="cov0" title="0">return result, nil</span>
}

func (a *AliyunProviderImpl) GetDisk(ctx context.Context, region string, diskID string) (*model.ResourceDisk, error) <span class="cov0" title="0">{
        if region == "" || diskID == "" </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("region and diskID cannot be empty")
        }</span>

        <span class="cov0" title="0">disk, err := a.diskService.GetDisk(ctx, region, diskID)
        if err != nil </span><span class="cov0" title="0">{
                a.logger.Error("failed to get disk detail", zap.Error(err), zap.String("diskID", diskID))
                return nil, fmt.Errorf("get disk detail failed: %w", err)
        }</span>

        <span class="cov0" title="0">if disk == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("disk not found")
        }</span>

        <span class="cov0" title="0">return a.convertToResourceDiskFromDetail(disk, region), nil</span>
}

func (a *AliyunProviderImpl) CreateDisk(ctx context.Context, region string, config *model.CreateDiskReq) error <span class="cov0" title="0">{
        if region == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region cannot be empty")
        }</span>
        <span class="cov0" title="0">if config == nil </span><span class="cov0" title="0">{
                return fmt.Errorf("config cannot be nil")
        }</span>

        <span class="cov0" title="0">req := &amp;aliyun.CreateDiskRequest{
                Region:       region,
                ZoneId:       config.ZoneId,
                DiskName:     config.DiskName,
                DiskCategory: config.DiskCategory,
                Size:         config.Size,
                Description:  config.Description,
        }

        _, err := a.diskService.CreateDisk(ctx, req)
        if err != nil </span><span class="cov0" title="0">{
                a.logger.Error("failed to create disk", zap.Error(err), zap.String("region", region))
                return fmt.Errorf("create disk failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

func (a *AliyunProviderImpl) DeleteDisk(ctx context.Context, region string, diskID string) error <span class="cov0" title="0">{
        if region == "" || diskID == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region and diskID cannot be empty")
        }</span>

        <span class="cov0" title="0">err := a.diskService.DeleteDisk(ctx, region, diskID)
        if err != nil </span><span class="cov0" title="0">{
                a.logger.Error("failed to delete disk", zap.Error(err), zap.String("diskID", diskID))
                return fmt.Errorf("delete disk failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

func (a *AliyunProviderImpl) AttachDisk(ctx context.Context, region string, diskID, instanceID string) error <span class="cov0" title="0">{
        if region == "" || diskID == "" || instanceID == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region, diskID and instanceID cannot be empty")
        }</span>

        <span class="cov0" title="0">err := a.diskService.AttachDisk(ctx, region, diskID, instanceID)
        if err != nil </span><span class="cov0" title="0">{
                a.logger.Error("failed to attach disk", zap.Error(err), zap.String("diskID", diskID), zap.String("instanceID", instanceID))
                return fmt.Errorf("attach disk failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

func (a *AliyunProviderImpl) DetachDisk(ctx context.Context, region string, diskID, instanceID string) error <span class="cov0" title="0">{
        if region == "" || diskID == "" || instanceID == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region, diskID and instanceID cannot be empty")
        }</span>

        <span class="cov0" title="0">err := a.diskService.DetachDisk(ctx, region, diskID, instanceID)
        if err != nil </span><span class="cov0" title="0">{
                a.logger.Error("failed to detach disk", zap.Error(err), zap.String("diskID", diskID), zap.String("instanceID", instanceID))
                return fmt.Errorf("detach disk failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

func (a *AliyunProviderImpl) ListRegionOptions(ctx context.Context) ([]*model.ListEcsResourceOptionsResp, error) <span class="cov0" title="0">{
        return nil, nil
}</span>

func (a *AliyunProviderImpl) ListRegionZones(ctx context.Context, region string) ([]*model.ListEcsResourceOptionsResp, error) <span class="cov0" title="0">{
        return nil, nil
}</span>

func (a *AliyunProviderImpl) ListRegionInstanceTypes(ctx context.Context, region string) ([]*model.ListEcsResourceOptionsResp, error) <span class="cov0" title="0">{
        return nil, nil
}</span>

func (a *AliyunProviderImpl) ListRegionImages(ctx context.Context, region string) ([]*model.ListEcsResourceOptionsResp, error) <span class="cov0" title="0">{
        return nil, nil
}</span>

func (a *AliyunProviderImpl) ListRegionSystemDiskCategories(ctx context.Context, region string) ([]*model.ListEcsResourceOptionsResp, error) <span class="cov0" title="0">{
        return nil, nil
}</span>

func (a *AliyunProviderImpl) ListRegionDataDiskCategories(ctx context.Context, region string) ([]*model.ListEcsResourceOptionsResp, error) <span class="cov0" title="0">{
        return nil, nil
}</span>

// 转换函数
func (a *AliyunProviderImpl) convertToResourceEcsFromListInstance(instance *ecs.DescribeInstancesResponseBodyInstancesInstance) *model.ResourceEcs <span class="cov0" title="0">{
        if instance == nil </span><span class="cov0" title="0">{
                return nil
        }</span>

        <span class="cov0" title="0">var securityGroupIds []string
        if instance.SecurityGroupIds != nil &amp;&amp; instance.SecurityGroupIds.SecurityGroupId != nil </span><span class="cov0" title="0">{
                securityGroupIds = tea.StringSliceValue(instance.SecurityGroupIds.SecurityGroupId)
        }</span>

        <span class="cov0" title="0">var privateIPs []string
        if instance.VpcAttributes != nil &amp;&amp; instance.VpcAttributes.PrivateIpAddress != nil &amp;&amp; instance.VpcAttributes.PrivateIpAddress.IpAddress != nil </span><span class="cov0" title="0">{
                privateIPs = tea.StringSliceValue(instance.VpcAttributes.PrivateIpAddress.IpAddress)
        }</span>

        <span class="cov0" title="0">var publicIPs []string
        if instance.PublicIpAddress != nil &amp;&amp; instance.PublicIpAddress.IpAddress != nil </span><span class="cov0" title="0">{
                publicIPs = tea.StringSliceValue(instance.PublicIpAddress.IpAddress)
        }</span>

        <span class="cov0" title="0">var vpcId string
        if instance.VpcAttributes != nil </span><span class="cov0" title="0">{
                vpcId = tea.StringValue(instance.VpcAttributes.VpcId)
        }</span>

        // 计算内存，阿里云返回的是MB，转换为GB
        <span class="cov0" title="0">memory := int(tea.Int32Value(instance.Memory)) / 1024
        if memory == 0 &amp;&amp; tea.Int32Value(instance.Memory) &gt; 0 </span><span class="cov0" title="0">{
                memory = 1 // 如果小于1GB但大于0，设为1GB
        }</span>

        <span class="cov0" title="0">var tags []string
        if instance.Tags != nil &amp;&amp; instance.Tags.Tag != nil </span><span class="cov0" title="0">{
                tags = make([]string, 0, len(instance.Tags.Tag))
                for _, tag := range instance.Tags.Tag </span><span class="cov0" title="0">{
                        if tag == nil || tag.TagKey == nil || tag.TagValue == nil </span><span class="cov0" title="0">{
                                continue</span>
                        }
                        <span class="cov0" title="0">tags = append(tags, fmt.Sprintf("%s=%s", tea.StringValue(tag.TagKey), tea.StringValue(tag.TagValue)))</span>
                }
        }

        <span class="cov0" title="0">lastSyncTime := time.Now()

        return &amp;model.ResourceEcs{
                InstanceName:       tea.StringValue(instance.InstanceName),
                InstanceId:         tea.StringValue(instance.InstanceId),
                Provider:           model.CloudProviderAliyun,
                RegionId:           tea.StringValue(instance.RegionId),
                ZoneId:             tea.StringValue(instance.ZoneId),
                VpcId:              vpcId,
                Status:             tea.StringValue(instance.Status),
                CreationTime:       tea.StringValue(instance.CreationTime),
                InstanceChargeType: tea.StringValue(instance.InstanceChargeType),
                Description:        tea.StringValue(instance.Description),
                SecurityGroupIds:   model.StringList(securityGroupIds),
                PrivateIpAddress:   model.StringList(privateIPs),
                PublicIpAddress:    model.StringList(publicIPs),
                LastSyncTime:       &amp;lastSyncTime,
                Tags:               model.StringList(tags),
                Cpu:                int(tea.Int32Value(instance.Cpu)),
                Memory:             memory,
                InstanceType:       tea.StringValue(instance.InstanceType),
                ImageId:            tea.StringValue(instance.ImageId),
                HostName:           tea.StringValue(instance.HostName),
                IpAddr:             getFirstIP(privateIPs),
        }</span>
}

func (a *AliyunProviderImpl) convertToResourceEcsFromInstanceDetail(instance *ecs.DescribeInstanceAttributeResponseBody) *model.ResourceEcs <span class="cov0" title="0">{
        if instance == nil </span><span class="cov0" title="0">{
                return nil
        }</span>

        <span class="cov0" title="0">var securityGroupIds []string
        if instance.SecurityGroupIds != nil &amp;&amp; instance.SecurityGroupIds.SecurityGroupId != nil </span><span class="cov0" title="0">{
                securityGroupIds = tea.StringSliceValue(instance.SecurityGroupIds.SecurityGroupId)
        }</span>

        <span class="cov0" title="0">var privateIPs []string
        if instance.VpcAttributes != nil &amp;&amp; instance.VpcAttributes.PrivateIpAddress != nil &amp;&amp; instance.VpcAttributes.PrivateIpAddress.IpAddress != nil </span><span class="cov0" title="0">{
                privateIPs = tea.StringSliceValue(instance.VpcAttributes.PrivateIpAddress.IpAddress)
        }</span>

        <span class="cov0" title="0">var publicIPs []string
        if instance.PublicIpAddress != nil &amp;&amp; instance.PublicIpAddress.IpAddress != nil </span><span class="cov0" title="0">{
                publicIPs = tea.StringSliceValue(instance.PublicIpAddress.IpAddress)
        }</span>

        <span class="cov0" title="0">var vpcId string
        if instance.VpcAttributes != nil </span><span class="cov0" title="0">{
                vpcId = tea.StringValue(instance.VpcAttributes.VpcId)
        }</span>

        // 计算内存，阿里云返回的是MB，转换为GB
        <span class="cov0" title="0">memory := int(tea.Int32Value(instance.Memory)) / 1024
        if memory == 0 &amp;&amp; tea.Int32Value(instance.Memory) &gt; 0 </span><span class="cov0" title="0">{
                memory = 1 // 如果小于1GB但大于0，设为1GB
        }</span>

        <span class="cov0" title="0">lastSyncTime := time.Now()

        return &amp;model.ResourceEcs{
                InstanceName:       tea.StringValue(instance.InstanceName),
                InstanceId:         tea.StringValue(instance.InstanceId),
                Provider:           model.CloudProviderAliyun,
                RegionId:           tea.StringValue(instance.RegionId),
                ZoneId:             tea.StringValue(instance.ZoneId),
                VpcId:              vpcId,
                Status:             tea.StringValue(instance.Status),
                CreationTime:       tea.StringValue(instance.CreationTime),
                InstanceChargeType: tea.StringValue(instance.InstanceChargeType),
                Description:        tea.StringValue(instance.Description),
                SecurityGroupIds:   model.StringList(securityGroupIds),
                PrivateIpAddress:   model.StringList(privateIPs),
                PublicIpAddress:    model.StringList(publicIPs),
                LastSyncTime:       &amp;lastSyncTime,
                Cpu:                int(tea.Int32Value(instance.Cpu)),
                Memory:             memory,
                InstanceType:       tea.StringValue(instance.InstanceType),
                ImageId:            tea.StringValue(instance.ImageId),
                HostName:           tea.StringValue(instance.HostName),
                IpAddr:             getFirstIP(privateIPs),
        }</span>
}

func (a *AliyunProviderImpl) convertToResourceVpcFromListVpc(vpcData *vpc.DescribeVpcsResponseBodyVpcsVpc, region string) *model.ResourceVpc <span class="cov0" title="0">{
        if vpcData == nil </span><span class="cov0" title="0">{
                return nil
        }</span>

        <span class="cov0" title="0">var tags []string
        if vpcData.Tags != nil &amp;&amp; vpcData.Tags.Tag != nil </span><span class="cov0" title="0">{
                tags = make([]string, 0, len(vpcData.Tags.Tag))
                for _, tag := range vpcData.Tags.Tag </span><span class="cov0" title="0">{
                        if tag == nil || tag.Key == nil || tag.Value == nil </span><span class="cov0" title="0">{
                                continue</span>
                        }
                        <span class="cov0" title="0">tags = append(tags, fmt.Sprintf("%s=%s", tea.StringValue(tag.Key), tea.StringValue(tag.Value)))</span>
                }
        }

        <span class="cov0" title="0">var vSwitchIds []string
        if vpcData.VSwitchIds != nil &amp;&amp; vpcData.VSwitchIds.VSwitchId != nil </span><span class="cov0" title="0">{
                vSwitchIds = tea.StringSliceValue(vpcData.VSwitchIds.VSwitchId)
        }</span>

        <span class="cov0" title="0">return &amp;model.ResourceVpc{
                InstanceName:    tea.StringValue(vpcData.VpcName),
                InstanceId:      tea.StringValue(vpcData.VpcId),
                Provider:        model.CloudProviderAliyun,
                RegionId:        region,
                VpcId:           tea.StringValue(vpcData.VpcId),
                Status:          tea.StringValue(vpcData.Status),
                CreationTime:    tea.StringValue(vpcData.CreationTime),
                Description:     tea.StringValue(vpcData.Description),
                LastSyncTime:    time.Now(),
                Tags:            model.StringList(tags),
                VpcName:         tea.StringValue(vpcData.VpcName),
                CidrBlock:       tea.StringValue(vpcData.CidrBlock),
                Ipv6CidrBlock:   tea.StringValue(vpcData.Ipv6CidrBlock),
                VSwitchIds:      model.StringList(vSwitchIds),
                IsDefault:       tea.BoolValue(vpcData.IsDefault),
                ResourceGroupId: tea.StringValue(vpcData.ResourceGroupId),
        }</span>
}

func (a *AliyunProviderImpl) convertToResourceVpcFromDetail(vpcDetail *vpc.DescribeVpcAttributeResponseBody, region string) *model.ResourceVpc <span class="cov0" title="0">{
        if vpcDetail == nil </span><span class="cov0" title="0">{
                return nil
        }</span>

        <span class="cov0" title="0">var tags []string
        if vpcDetail.Tags != nil &amp;&amp; vpcDetail.Tags.Tag != nil </span><span class="cov0" title="0">{
                tags = make([]string, 0, len(vpcDetail.Tags.Tag))
                for _, tag := range vpcDetail.Tags.Tag </span><span class="cov0" title="0">{
                        if tag == nil || tag.Key == nil || tag.Value == nil </span><span class="cov0" title="0">{
                                continue</span>
                        }
                        <span class="cov0" title="0">tags = append(tags, fmt.Sprintf("%s=%s", tea.StringValue(tag.Key), tea.StringValue(tag.Value)))</span>
                }
        }

        <span class="cov0" title="0">var vSwitchIds []string
        if vpcDetail.VSwitchIds != nil &amp;&amp; vpcDetail.VSwitchIds.VSwitchId != nil </span><span class="cov0" title="0">{
                vSwitchIds = tea.StringSliceValue(vpcDetail.VSwitchIds.VSwitchId)
        }</span>

        <span class="cov0" title="0">return &amp;model.ResourceVpc{
                InstanceName:    tea.StringValue(vpcDetail.VpcName),
                InstanceId:      tea.StringValue(vpcDetail.VpcId),
                Provider:        model.CloudProviderAliyun,
                RegionId:        region,
                VpcId:           tea.StringValue(vpcDetail.VpcId),
                Status:          tea.StringValue(vpcDetail.Status),
                CreationTime:    tea.StringValue(vpcDetail.CreationTime),
                Description:     tea.StringValue(vpcDetail.Description),
                LastSyncTime:    time.Now(),
                Tags:            model.StringList(tags),
                VpcName:         tea.StringValue(vpcDetail.VpcName),
                CidrBlock:       tea.StringValue(vpcDetail.CidrBlock),
                Ipv6CidrBlock:   tea.StringValue(vpcDetail.Ipv6CidrBlock),
                VSwitchIds:      model.StringList(vSwitchIds),
                IsDefault:       tea.BoolValue(vpcDetail.IsDefault),
                ResourceGroupId: tea.StringValue(vpcDetail.ResourceGroupId),
        }</span>
}

func (a *AliyunProviderImpl) convertToResourceSecurityGroupFromList(sg *ecs.DescribeSecurityGroupsResponseBodySecurityGroupsSecurityGroup, region string) *model.ResourceSecurityGroup <span class="cov0" title="0">{
        if sg == nil </span><span class="cov0" title="0">{
                return nil
        }</span>

        <span class="cov0" title="0">var tags []string
        if sg.Tags != nil &amp;&amp; sg.Tags.Tag != nil </span><span class="cov0" title="0">{
                tags = make([]string, 0, len(sg.Tags.Tag))
                for _, tag := range sg.Tags.Tag </span><span class="cov0" title="0">{
                        if tag == nil || tag.TagKey == nil || tag.TagValue == nil </span><span class="cov0" title="0">{
                                continue</span>
                        }
                        <span class="cov0" title="0">tags = append(tags, fmt.Sprintf("%s=%s", tea.StringValue(tag.TagKey), tea.StringValue(tag.TagValue)))</span>
                }
        }

        <span class="cov0" title="0">return &amp;model.ResourceSecurityGroup{
                InstanceName:      tea.StringValue(sg.SecurityGroupName),
                InstanceId:        tea.StringValue(sg.SecurityGroupId),
                Provider:          model.CloudProviderAliyun,
                RegionId:          region,
                VpcId:             tea.StringValue(sg.VpcId),
                Description:       tea.StringValue(sg.Description),
                LastSyncTime:      time.Now(),
                Tags:              model.StringList(tags),
                SecurityGroupName: tea.StringValue(sg.SecurityGroupName),
        }</span>
}

func (a *AliyunProviderImpl) convertToResourceSecurityGroupFromDetail(sg *ecs.DescribeSecurityGroupAttributeResponseBody, region string) *model.ResourceSecurityGroup <span class="cov0" title="0">{
        return &amp;model.ResourceSecurityGroup{
                InstanceName:      tea.StringValue(sg.SecurityGroupName),
                InstanceId:        tea.StringValue(sg.SecurityGroupId),
                Provider:          model.CloudProviderAliyun,
                RegionId:          region,
                VpcId:             tea.StringValue(sg.VpcId),
                Description:       tea.StringValue(sg.Description),
                LastSyncTime:      time.Now(),
                SecurityGroupName: tea.StringValue(sg.SecurityGroupName),
        }
}</span>

func (a *AliyunProviderImpl) convertToResourceDiskFromList(disk *ecs.DescribeDisksResponseBodyDisksDisk, region string) *model.ResourceDisk <span class="cov0" title="0">{
        if disk == nil </span><span class="cov0" title="0">{
                return nil
        }</span>

        <span class="cov0" title="0">var tags []string
        if disk.Tags != nil &amp;&amp; disk.Tags.Tag != nil </span><span class="cov0" title="0">{
                tags = make([]string, 0, len(disk.Tags.Tag))
                for _, tag := range disk.Tags.Tag </span><span class="cov0" title="0">{
                        if tag == nil || tag.TagKey == nil || tag.TagValue == nil </span><span class="cov0" title="0">{
                                continue</span>
                        }
                        <span class="cov0" title="0">tags = append(tags, fmt.Sprintf("%s=%s", tea.StringValue(tag.TagKey), tea.StringValue(tag.TagValue)))</span>
                }
        }

        <span class="cov0" title="0">return &amp;model.ResourceDisk{
                InstanceName: tea.StringValue(disk.DiskName),
                InstanceId:   tea.StringValue(disk.DiskId),
                Provider:     model.CloudProviderAliyun,
                RegionId:     region,
                ZoneId:       tea.StringValue(disk.ZoneId),
                Status:       tea.StringValue(disk.Status),
                CreationTime: tea.StringValue(disk.CreationTime),
                Description:  tea.StringValue(disk.Description),
                LastSyncTime: time.Now(),
                Tags:         model.StringList(tags),
                DiskID:       tea.StringValue(disk.DiskId),
                DiskName:     tea.StringValue(disk.DiskName),
                Size:         int(tea.Int32Value(disk.Size)),
                Category:     tea.StringValue(disk.Category),
                InstanceID:   tea.StringValue(disk.InstanceId),
        }</span>
}

func (a *AliyunProviderImpl) convertToResourceDiskFromDetail(disk *ecs.DescribeDisksResponseBodyDisksDisk, region string) *model.ResourceDisk <span class="cov0" title="0">{
        if disk == nil </span><span class="cov0" title="0">{
                return nil
        }</span>

        <span class="cov0" title="0">var tags []string
        if disk.Tags != nil &amp;&amp; disk.Tags.Tag != nil </span><span class="cov0" title="0">{
                tags = make([]string, 0, len(disk.Tags.Tag))
                for _, tag := range disk.Tags.Tag </span><span class="cov0" title="0">{
                        if tag == nil || tag.TagKey == nil || tag.TagValue == nil </span><span class="cov0" title="0">{
                                continue</span>
                        }
                        <span class="cov0" title="0">tags = append(tags, fmt.Sprintf("%s=%s", tea.StringValue(tag.TagKey), tea.StringValue(tag.TagValue)))</span>
                }
        }

        <span class="cov0" title="0">return &amp;model.ResourceDisk{
                InstanceName: tea.StringValue(disk.DiskName),
                InstanceId:   tea.StringValue(disk.DiskId),
                Provider:     model.CloudProviderAliyun,
                RegionId:     region,
                ZoneId:       tea.StringValue(disk.ZoneId),
                Status:       tea.StringValue(disk.Status),
                CreationTime: tea.StringValue(disk.CreationTime),
                Description:  tea.StringValue(disk.Description),
                LastSyncTime: time.Now(),
                Tags:         model.StringList(tags),
                DiskID:       tea.StringValue(disk.DiskId),
                DiskName:     tea.StringValue(disk.DiskName),
                Size:         int(tea.Int32Value(disk.Size)),
                Category:     tea.StringValue(disk.Category),
                InstanceID:   tea.StringValue(disk.InstanceId),
        }</span>
}

// 工具函数
func getFirstIP(ips []string) string <span class="cov0" title="0">{
        if len(ips) &gt; 0 </span><span class="cov0" title="0">{
                return ips[0]
        }</span>
        <span class="cov0" title="0">return ""</span>
}
</pre>
		
		<pre class="file" id="file1" style="display: none">/*
 * MIT License
 *
 * Copyright (c) 2024 Bamboo
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

package provider

import (
        "fmt"

        "github.com/GoSimplicity/AI-CloudOps/internal/model"
)

type ProviderFactory struct {
        providers map[model.CloudProvider]Provider
}

func NewProviderFactory(
        aliyun *AliyunProviderImpl,
        huawei *HuaweiProviderImpl,
) *ProviderFactory <span class="cov0" title="0">{
        return &amp;ProviderFactory{
                providers: map[model.CloudProvider]Provider{
                        model.CloudProviderAliyun: aliyun,
                        model.CloudProviderHuawei: huawei,
                },
        }
}</span>

func (f *ProviderFactory) GetProvider(providerType model.CloudProvider) (Provider, error) <span class="cov0" title="0">{
        provider, ok := f.providers[providerType]
        if !ok </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("不支持的云提供商: %s", providerType)
        }</span>
        <span class="cov0" title="0">return provider, nil</span>
}
</pre>
		
		<pre class="file" id="file2" style="display: none">/*
 * MIT License
 *
 * Copyright (c) 2024 Bamboo
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

package provider

import (
        "context"
        "encoding/json"
        "fmt"
        "os"
        "strconv"
        "strings"
        "time"

        "github.com/GoSimplicity/AI-CloudOps/internal/model"
        "github.com/GoSimplicity/AI-CloudOps/pkg/huawei"
        ecsmodel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ecs/v2/model"
        evsmodel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/evs/v2/model"
        vpcmodel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/vpc/v3/model"
        "go.uber.org/zap"
)

// HuaweiCloudConfig 华为云配置
// 该配置结构体用于管理华为云提供商的动态配置信息
// 支持区域自动发现、端点配置、默认参数设置等功能
type HuaweiCloudConfig struct {
        // 动态发现的区域配置（空map，后续通过API填充）
        // 区域信息将通过华为云SDK动态获取，而非硬编码
        Regions map[string]HuaweiRegionConfig `json:"regions"`
        // 默认配置 - 用于设置各种操作的默认参数
        Defaults HuaweiDefaultConfig `json:"defaults"`
        // 端点配置 - 管理华为云各服务的API端点
        Endpoints HuaweiEndpointConfig `json:"endpoints"`
        // 区域发现配置 - 控制区域自动发现的参数
        Discovery HuaweiDiscoveryConfig `json:"discovery"`
}

// HuaweiRegionConfig 华为云区域配置
// 存储单个区域的详细配置信息
type HuaweiRegionConfig struct {
        RegionID     string                 `json:"region_id"`              // 区域ID，如 cn-north-1
        LocalName    string                 `json:"local_name"`             // 区域的中文显示名称
        CityName     string                 `json:"city_name"`              // 城市名称
        Enabled      bool                   `json:"enabled"`                // 是否启用该区域
        ZonePrefix   string                 `json:"zone_prefix"`            // 可用区前缀
        IsAccessible bool                   `json:"is_accessible"`          // 区域是否可访问
        LastChecked  *time.Time             `json:"last_checked,omitempty"` // 最后检查时间
        Metadata     map[string]interface{} `json:"metadata,omitempty"`     // 额外的元数据信息
}

// HuaweiDefaultConfig 华为云默认配置
// 定义各种操作的默认参数值
type HuaweiDefaultConfig struct {
        InstanceChargeType string `json:"instance_charge_type"` // 实例计费类型，默认按需付费
        ForceDelete        bool   `json:"force_delete"`         // 是否强制删除资源
        ForceStop          bool   `json:"force_stop"`           // 是否强制停止实例
        PageSize           int    `json:"page_size"`            // 分页大小，默认50
        MaxRetries         int    `json:"max_retries"`          // 最大重试次数，默认3
        TimeoutSeconds     int    `json:"timeout_seconds"`      // 超时时间（秒），默认300
        ConcurrentLimit    int    `json:"concurrent_limit"`     // 并发限制，默认10
}

// HuaweiEndpointConfig 华为云端点配置
// 管理华为云各服务的API端点模板和自定义端点
type HuaweiEndpointConfig struct {
        ECSTemplate         string            `json:"ecs_template"`               // ECS服务端点模板
        VPCTemplate         string            `json:"vpc_template"`               // VPC服务端点模板
        EVSTemplate         string            `json:"evs_template"`               // EVS服务端点模板
        IAMTemplate         string            `json:"iam_template"`               // IAM服务端点模板
        CustomEndpoints     map[string]string `json:"custom_endpoints,omitempty"` // 自定义端点映射
        GlobalEndpoint      string            `json:"global_endpoint"`            // 全局端点
        InternationalSuffix string            `json:"international_suffix"`       // 国际版后缀
}

// HuaweiDiscoveryConfig 华为云区域发现配置
// 控制区域自动发现的行为和参数
type HuaweiDiscoveryConfig struct {
        EnableAutoDiscovery bool          `json:"enable_auto_discovery"` // 是否启用自动发现
        CacheTimeout        time.Duration `json:"cache_timeout"`         // 缓存超时时间
        ProbeTimeout        time.Duration `json:"probe_timeout"`         // 探测超时时间
        MaxConcurrent       int           `json:"max_concurrent"`        // 最大并发探测数
        RetryAttempts       int           `json:"retry_attempts"`        // 重试次数
        RetryDelay          time.Duration `json:"retry_delay"`           // 重试延迟时间
}

// HuaweiRegionInfo 华为云区域信息
type HuaweiRegionInfo struct {
        RegionID     string    `json:"region_id"`
        LocalName    string    `json:"local_name"`
        IsAccessible bool      `json:"is_accessible"`
        LastChecked  time.Time `json:"last_checked"`
}

// getDefaultHuaweiConfig 获取默认华为云配置（完全动态）
func getDefaultHuaweiConfig() *HuaweiCloudConfig <span class="cov8" title="1">{
        return &amp;HuaweiCloudConfig{
                // 初始化空的区域配置，后续通过API动态发现
                Regions: make(map[string]HuaweiRegionConfig),

                // 默认配置 - 使用合理的默认值
                Defaults: HuaweiDefaultConfig{
                        InstanceChargeType: "PostPaid", // 按需付费
                        ForceDelete:        false,      // 安全起见，默认不强制删除
                        ForceStop:          false,      // 安全起见，默认不强制停止
                        PageSize:           50,         // 合理的分页大小
                        MaxRetries:         3,          // 重试次数
                        TimeoutSeconds:     300,        // 5分钟超时
                        ConcurrentLimit:    10,         // 并发限制
                },

                // 端点配置 - 使用华为云标准端点模板
                Endpoints: HuaweiEndpointConfig{
                        ECSTemplate:         "ecs.%s.myhuaweicloud.com",
                        VPCTemplate:         "vpc.%s.myhuaweicloud.com",
                        EVSTemplate:         "evs.%s.myhuaweicloud.com",
                        IAMTemplate:         "iam.%s.myhuaweicloud.com",
                        CustomEndpoints:     make(map[string]string),
                        GlobalEndpoint:      "myhuaweicloud.com",
                        InternationalSuffix: "myhuaweicloud.com",
                },

                // 区域发现配置
                Discovery: HuaweiDiscoveryConfig{
                        EnableAutoDiscovery: true,
                        CacheTimeout:        6 * time.Hour,   // 6小时缓存
                        ProbeTimeout:        5 * time.Second, // 5秒探测超时
                        MaxConcurrent:       20,              // 最大并发探测数
                        RetryAttempts:       2,               // 重试次数
                        RetryDelay:          1 * time.Second, // 重试延迟
                },
        }
}</span>

type HuaweiProviderImpl struct {
        logger               *zap.Logger
        sdk                  *huawei.SDK
        ecsService           *huawei.EcsService
        vpcService           *huawei.VpcService
        diskService          *huawei.DiskService
        securityGroupService *huawei.SecurityGroupService
        config               *HuaweiCloudConfig
        cachedRegions        []*model.RegionResp          // 缓存的区域列表
        regionsCacheTime     time.Time                    // 区域缓存时间
        discoveredRegions    map[string]*HuaweiRegionInfo // 动态发现的区域信息
}

func NewHuaweiProvider(logger *zap.Logger) *HuaweiProviderImpl <span class="cov8" title="1">{
        return &amp;HuaweiProviderImpl{
                logger:            logger,
                config:            getDefaultHuaweiConfig(),
                discoveredRegions: make(map[string]*HuaweiRegionInfo),
        }
}</span>

// InitializeProvider 初始化华为云提供商
func (h *HuaweiProviderImpl) InitializeProvider(accessKey, secretKey string) error <span class="cov0" title="0">{
        if accessKey == "" || secretKey == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("华为云访问密钥不能为空")
        }</span>

        // 创建SDK实例
        <span class="cov0" title="0">sdk := huawei.NewSDK(h.logger, accessKey, secretKey)

        // 初始化各个服务
        h.sdk = sdk
        h.ecsService = huawei.NewEcsService(sdk)
        h.vpcService = huawei.NewVpcService(sdk)
        h.diskService = huawei.NewDiskService(sdk)
        h.securityGroupService = huawei.NewSecurityGroupService(sdk)

        h.logger.Info("华为云提供商初始化成功")
        return nil</span>
}

// ValidateCredentials 验证华为云凭证
func (h *HuaweiProviderImpl) ValidateCredentials(ctx context.Context) error <span class="cov0" title="0">{
        if h.sdk == nil </span><span class="cov0" title="0">{
                return fmt.Errorf("华为云SDK未初始化")
        }</span>

        // 通过列出区域来验证凭证
        <span class="cov0" title="0">_, err := h.getHuaweiRegionsFromSDK()
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("华为云凭证验证失败", zap.Error(err))
                return fmt.Errorf("华为云凭证验证失败: %w", err)
        }</span>

        <span class="cov0" title="0">h.logger.Info("华为云凭证验证成功")
        return nil</span>
}

// 基础服务
func (h *HuaweiProviderImpl) SyncResources(ctx context.Context, region string) error <span class="cov0" title="0">{
        if region == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region cannot be empty")
        }</span>

        <span class="cov0" title="0">h.logger.Info("开始同步华为云资源", zap.String("region", region))

        // 检查SDK服务是否已初始化
        if h.sdk == nil </span><span class="cov0" title="0">{
                return fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        // 并发同步不同类型的资源
        <span class="cov0" title="0">errChan := make(chan error, 4)

        // 同步ECS实例
        go func() </span><span class="cov0" title="0">{
                if err := h.syncEcsInstances(ctx, region); err != nil </span><span class="cov0" title="0">{
                        h.logger.Error("同步ECS实例失败", zap.Error(err), zap.String("region", region))
                        errChan &lt;- fmt.Errorf("同步ECS实例失败: %w", err)
                }</span> else<span class="cov0" title="0"> {
                        errChan &lt;- nil
                }</span>
        }()

        // 同步VPC资源
        <span class="cov0" title="0">go func() </span><span class="cov0" title="0">{
                if err := h.syncVpcResources(ctx, region); err != nil </span><span class="cov0" title="0">{
                        h.logger.Error("同步VPC资源失败", zap.Error(err), zap.String("region", region))
                        errChan &lt;- fmt.Errorf("同步VPC资源失败: %w", err)
                }</span> else<span class="cov0" title="0"> {
                        errChan &lt;- nil
                }</span>
        }()

        // 同步安全组资源
        <span class="cov0" title="0">go func() </span><span class="cov0" title="0">{
                if err := h.syncSecurityGroupResources(ctx, region); err != nil </span><span class="cov0" title="0">{
                        h.logger.Error("同步安全组资源失败", zap.Error(err), zap.String("region", region))
                        errChan &lt;- fmt.Errorf("同步安全组资源失败: %w", err)
                }</span> else<span class="cov0" title="0"> {
                        errChan &lt;- nil
                }</span>
        }()

        // 同步磁盘资源
        <span class="cov0" title="0">go func() </span><span class="cov0" title="0">{
                if err := h.syncDiskResources(ctx, region); err != nil </span><span class="cov0" title="0">{
                        h.logger.Error("同步磁盘资源失败", zap.Error(err), zap.String("region", region))
                        errChan &lt;- fmt.Errorf("同步磁盘资源失败: %w", err)
                }</span> else<span class="cov0" title="0"> {
                        errChan &lt;- nil
                }</span>
        }()

        // 等待所有同步任务完成
        <span class="cov0" title="0">var errors []error
        for i := 0; i &lt; 4; i++ </span><span class="cov0" title="0">{
                if err := &lt;-errChan; err != nil </span><span class="cov0" title="0">{
                        errors = append(errors, err)
                }</span>
        }

        <span class="cov0" title="0">if len(errors) &gt; 0 </span><span class="cov0" title="0">{
                return fmt.Errorf("资源同步过程中发生错误: %v", errors)
        }</span>

        <span class="cov0" title="0">h.logger.Info("华为云资源同步完成", zap.String("region", region))
        return nil</span>
}

// syncEcsInstances 同步ECS实例资源
func (h *HuaweiProviderImpl) syncEcsInstances(ctx context.Context, region string) error <span class="cov0" title="0">{
        h.logger.Debug("开始同步ECS实例", zap.String("region", region))

        page := 1
        pageSize := 50
        totalSynced := 0

        for </span><span class="cov0" title="0">{
                instances, total, err := h.ListInstances(ctx, region, page, pageSize)
                if err != nil </span><span class="cov0" title="0">{
                        return fmt.Errorf("获取ECS实例列表失败: %w", err)
                }</span>

                <span class="cov0" title="0">if len(instances) == 0 </span><span class="cov0" title="0">{
                        break</span>
                }

                // 处理实例数据（这里可以添加数据库存储逻辑）
                <span class="cov0" title="0">for _, instance := range instances </span><span class="cov0" title="0">{
                        h.logger.Debug("同步ECS实例",
                                zap.String("instanceId", instance.InstanceId),
                                zap.String("instanceName", instance.InstanceName),
                                zap.String("status", instance.Status))
                }</span>

                <span class="cov0" title="0">totalSynced += len(instances)
                h.logger.Debug("ECS实例同步进度",
                        zap.Int("synced", totalSynced),
                        zap.Int64("total", total),
                        zap.String("region", region))

                // 检查是否还有更多数据
                if totalSynced &gt;= int(total) || len(instances) &lt; pageSize </span><span class="cov0" title="0">{
                        break</span>
                }
                <span class="cov0" title="0">page++</span>
        }

        <span class="cov0" title="0">h.logger.Info("ECS实例同步完成", zap.Int("totalSynced", totalSynced), zap.String("region", region))
        return nil</span>
}

// syncVpcResources 同步VPC资源
func (h *HuaweiProviderImpl) syncVpcResources(ctx context.Context, region string) error <span class="cov0" title="0">{
        h.logger.Debug("开始同步VPC资源", zap.String("region", region))

        page := 1
        pageSize := 50
        totalSynced := 0

        for </span><span class="cov0" title="0">{
                vpcs, err := h.ListVPCs(ctx, region, page, pageSize)
                if err != nil </span><span class="cov0" title="0">{
                        return fmt.Errorf("获取VPC列表失败: %w", err)
                }</span>

                <span class="cov0" title="0">if len(vpcs) == 0 </span><span class="cov0" title="0">{
                        break</span>
                }

                // 处理VPC数据（这里可以添加数据库存储逻辑）
                <span class="cov0" title="0">for _, vpc := range vpcs </span><span class="cov0" title="0">{
                        h.logger.Debug("同步VPC",
                                zap.String("vpcId", vpc.VpcId),
                                zap.String("vpcName", vpc.VpcName),
                                zap.String("status", vpc.Status))
                }</span>

                <span class="cov0" title="0">totalSynced += len(vpcs)
                h.logger.Debug("VPC同步进度",
                        zap.Int("synced", totalSynced),
                        zap.String("region", region))

                // 检查是否还有更多数据
                if len(vpcs) &lt; pageSize </span><span class="cov0" title="0">{
                        break</span>
                }
                <span class="cov0" title="0">page++</span>
        }

        <span class="cov0" title="0">h.logger.Info("VPC资源同步完成", zap.Int("totalSynced", totalSynced), zap.String("region", region))
        return nil</span>
}

// syncSecurityGroupResources 同步安全组资源
func (h *HuaweiProviderImpl) syncSecurityGroupResources(ctx context.Context, region string) error <span class="cov0" title="0">{
        h.logger.Debug("开始同步安全组资源", zap.String("region", region))

        page := 1
        pageSize := 50
        totalSynced := 0

        for </span><span class="cov0" title="0">{
                securityGroups, err := h.ListSecurityGroups(ctx, region, page, pageSize)
                if err != nil </span><span class="cov0" title="0">{
                        return fmt.Errorf("获取安全组列表失败: %w", err)
                }</span>

                <span class="cov0" title="0">if len(securityGroups) == 0 </span><span class="cov0" title="0">{
                        break</span>
                }

                // 处理安全组数据（这里可以添加数据库存储逻辑）
                <span class="cov0" title="0">for _, sg := range securityGroups </span><span class="cov0" title="0">{
                        h.logger.Debug("同步安全组",
                                zap.String("securityGroupId", sg.InstanceId),
                                zap.String("securityGroupName", sg.SecurityGroupName),
                                zap.String("status", sg.Status))
                }</span>

                <span class="cov0" title="0">totalSynced += len(securityGroups)
                h.logger.Debug("安全组同步进度",
                        zap.Int("synced", totalSynced),
                        zap.String("region", region))

                // 检查是否还有更多数据
                if len(securityGroups) &lt; pageSize </span><span class="cov0" title="0">{
                        break</span>
                }
                <span class="cov0" title="0">page++</span>
        }

        <span class="cov0" title="0">h.logger.Info("安全组资源同步完成", zap.Int("totalSynced", totalSynced), zap.String("region", region))
        return nil</span>
}

// syncDiskResources 同步磁盘资源
func (h *HuaweiProviderImpl) syncDiskResources(ctx context.Context, region string) error <span class="cov0" title="0">{
        h.logger.Debug("开始同步磁盘资源", zap.String("region", region))

        page := 1
        pageSize := 50
        totalSynced := 0

        for </span><span class="cov0" title="0">{
                disks, err := h.ListDisks(ctx, region, page, pageSize)
                if err != nil </span><span class="cov0" title="0">{
                        return fmt.Errorf("获取磁盘列表失败: %w", err)
                }</span>

                <span class="cov0" title="0">if len(disks) == 0 </span><span class="cov0" title="0">{
                        break</span>
                }

                // 处理磁盘数据（这里可以添加数据库存储逻辑）
                <span class="cov0" title="0">for _, disk := range disks </span><span class="cov0" title="0">{
                        h.logger.Debug("同步磁盘",
                                zap.String("diskId", disk.DiskID),
                                zap.String("diskName", disk.DiskName),
                                zap.Int("size", disk.Size),
                                zap.String("status", disk.Status))
                }</span>

                <span class="cov0" title="0">totalSynced += len(disks)
                h.logger.Debug("磁盘同步进度",
                        zap.Int("synced", totalSynced),
                        zap.String("region", region))

                // 检查是否还有更多数据
                if len(disks) &lt; pageSize </span><span class="cov0" title="0">{
                        break</span>
                }
                <span class="cov0" title="0">page++</span>
        }

        <span class="cov0" title="0">h.logger.Info("磁盘资源同步完成", zap.Int("totalSynced", totalSynced), zap.String("region", region))
        return nil</span>
}

func (h *HuaweiProviderImpl) ListRegions(ctx context.Context) ([]*model.RegionResp, error) <span class="cov8" title="1">{
        // 检查缓存是否有效（缓存1小时）
        if h.cachedRegions != nil &amp;&amp; time.Since(h.regionsCacheTime) &lt; time.Hour </span><span class="cov0" title="0">{
                h.logger.Debug("使用缓存的区域列表", zap.Int("count", len(h.cachedRegions)))
                return h.cachedRegions, nil
        }</span>

        // 缓存过期或不存在，重新获取
        <span class="cov8" title="1">regions, err := h.getHuaweiRegionsFromSDK()
        if err != nil </span><span class="cov8" title="1">{
                h.logger.Error("获取华为云区域列表失败", zap.Error(err))
                return nil, err
        }</span>

        // 更新缓存
        <span class="cov0" title="0">h.cachedRegions = regions
        h.regionsCacheTime = time.Now()

        return regions, nil</span>
}

// RefreshRegions 刷新区域缓存
func (h *HuaweiProviderImpl) RefreshRegions(ctx context.Context) error <span class="cov0" title="0">{
        h.logger.Info("开始刷新华为云区域缓存")

        regions, err := h.getHuaweiRegionsFromSDK()
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("刷新华为云区域列表失败", zap.Error(err))
                return fmt.Errorf("刷新区域列表失败: %w", err)
        }</span>

        // 更新缓存
        <span class="cov0" title="0">h.cachedRegions = regions
        h.regionsCacheTime = time.Now()

        h.logger.Info("华为云区域缓存刷新成功", zap.Int("count", len(regions)))
        return nil</span>
}

// SyncRegionsWithCredentials 使用新的凭证同步区域信息
func (h *HuaweiProviderImpl) SyncRegionsWithCredentials(ctx context.Context, accessKey, secretKey string) error <span class="cov0" title="0">{
        // 临时初始化SDK来验证凭证
        tempSDK := huawei.NewSDK(h.logger, accessKey, secretKey)
        tempEcsService := huawei.NewEcsService(tempSDK)

        h.logger.Info("开始使用新凭证同步华为云区域")

        regions := []*model.RegionResp{}
        knownRegions := h.getKnownRegions()

        // 使用新凭证验证区域
        for _, regionInfo := range knownRegions </span><span class="cov0" title="0">{
                ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
                _, err := tempEcsService.ListInstances(ctx, &amp;huawei.ListInstancesRequest{
                        Region: regionInfo.RegionID,
                        Page:   1,
                        Size:   1,
                })
                cancel()

                if err == nil </span><span class="cov0" title="0">{
                        endpoint := fmt.Sprintf(h.config.Endpoints.ECSTemplate, regionInfo.RegionID)
                        regions = append(regions, &amp;model.RegionResp{
                                RegionId:       regionInfo.RegionID,
                                LocalName:      regionInfo.LocalName,
                                RegionEndpoint: endpoint,
                        })
                        h.logger.Debug("新凭证验证区域成功", zap.String("regionId", regionInfo.RegionID))
                }</span> else<span class="cov0" title="0"> {
                        h.logger.Debug("新凭证验证区域失败", zap.String("regionId", regionInfo.RegionID), zap.Error(err))
                }</span>
        }

        <span class="cov0" title="0">if len(regions) == 0 </span><span class="cov0" title="0">{
                return fmt.Errorf("使用提供的凭证无法访问任何华为云区域，请检查AKSK权限")
        }</span>

        // 凭证验证成功，更新SDK和服务
        <span class="cov0" title="0">h.sdk = tempSDK
        h.ecsService = tempEcsService
        h.vpcService = huawei.NewVpcService(tempSDK)
        h.diskService = huawei.NewDiskService(tempSDK)
        h.securityGroupService = huawei.NewSecurityGroupService(tempSDK)

        // 更新区域缓存
        h.cachedRegions = regions
        h.regionsCacheTime = time.Now()

        h.logger.Info("使用新凭证同步华为云区域成功",
                zap.Int("可访问区域数", len(regions)),
                zap.Strings("区域列表", h.getRegionIDs(regions)))

        return nil</span>
}

// getRegionIDs 提取区域ID列表
func (h *HuaweiProviderImpl) getRegionIDs(regions []*model.RegionResp) []string <span class="cov0" title="0">{
        var regionIDs []string
        for _, region := range regions </span><span class="cov0" title="0">{
                regionIDs = append(regionIDs, region.RegionId)
        }</span>
        <span class="cov0" title="0">return regionIDs</span>
}

// getHuaweiRegionsFromSDK 通过华为云API动态发现区域信息
func (h *HuaweiProviderImpl) getHuaweiRegionsFromSDK() ([]*model.RegionResp, error) <span class="cov8" title="1">{
        if h.sdk == nil </span><span class="cov8" title="1">{
                return nil, fmt.Errorf("华为云SDK未初始化")
        }</span>

        // 如果已经有发现的区域且在有效期内，直接返回
        <span class="cov0" title="0">if len(h.discoveredRegions) &gt; 0 </span><span class="cov0" title="0">{
                var regions []*model.RegionResp
                for _, regionInfo := range h.discoveredRegions </span><span class="cov0" title="0">{
                        if regionInfo.IsAccessible &amp;&amp; time.Since(regionInfo.LastChecked) &lt; 6*time.Hour </span><span class="cov0" title="0">{
                                endpoint := fmt.Sprintf(h.config.Endpoints.ECSTemplate, regionInfo.RegionID)
                                regions = append(regions, &amp;model.RegionResp{
                                        RegionId:       regionInfo.RegionID,
                                        LocalName:      regionInfo.LocalName,
                                        RegionEndpoint: endpoint,
                                })
                        }</span>
                }
                <span class="cov0" title="0">if len(regions) &gt; 0 </span><span class="cov0" title="0">{
                        h.logger.Debug("使用已发现的区域信息", zap.Int("count", len(regions)))
                        return regions, nil
                }</span>
        }

        // 动态发现区域
        <span class="cov0" title="0">h.logger.Info("开始动态发现华为云区域")
        return h.discoverRegionsFromAPI()</span>
}

// discoverRegionsFromAPI 通过API动态发现区域
// 该方法使用华为云SDK动态发现可用的区域列表
// 支持并发探测以提高发现效率，并自动缓存发现的区域信息
func (h *HuaweiProviderImpl) discoverRegionsFromAPI() ([]*model.RegionResp, error) <span class="cov0" title="0">{
        // 初始化发现的区域map
        if h.discoveredRegions == nil </span><span class="cov0" title="0">{
                h.discoveredRegions = make(map[string]*HuaweiRegionInfo)
        }</span>

        // 通过华为云SDK动态获取可用区域列表
        <span class="cov0" title="0">regionPatterns, err := h.getAvailableRegionsFromSDK()
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Warn("无法通过SDK获取区域列表，使用智能探测", zap.Error(err))
                // 如果SDK无法提供区域列表，使用智能探测方法
                regionPatterns = h.generateRegionPatterns()
        }</span>

        <span class="cov0" title="0">var validRegions []*model.RegionResp

        // 并发探测区域以提高效率
        type regionResult struct {
                regionID string
                valid    bool
                error    error
        }

        resultChan := make(chan regionResult, len(regionPatterns))

        // 启动并发探测任务
        for _, regionID := range regionPatterns </span><span class="cov0" title="0">{
                go func(rID string) </span><span class="cov0" title="0">{
                        valid := h.probeRegion(rID)
                        resultChan &lt;- regionResult{
                                regionID: rID,
                                valid:    valid,
                                error:    nil,
                        }
                }</span>(regionID)
        }

        // 收集探测结果
        <span class="cov0" title="0">for i := 0; i &lt; len(regionPatterns); i++ </span><span class="cov0" title="0">{
                result := &lt;-resultChan

                if result.valid </span><span class="cov0" title="0">{
                        // 生成区域显示名称
                        localName := h.generateRegionLocalName(result.regionID)

                        // 更新发现的区域信息到缓存
                        h.discoveredRegions[result.regionID] = &amp;HuaweiRegionInfo{
                                RegionID:     result.regionID,
                                LocalName:    localName,
                                IsAccessible: true,
                                LastChecked:  time.Now(),
                        }

                        // 生成区域响应对象
                        endpoint := fmt.Sprintf(h.config.Endpoints.ECSTemplate, result.regionID)
                        validRegions = append(validRegions, &amp;model.RegionResp{
                                RegionId:       result.regionID,
                                LocalName:      localName,
                                RegionEndpoint: endpoint,
                        })

                        h.logger.Debug("发现可访问区域", zap.String("regionId", result.regionID))
                }</span> else<span class="cov0" title="0"> {
                        // 记录不可访问的区域信息
                        h.discoveredRegions[result.regionID] = &amp;HuaweiRegionInfo{
                                RegionID:     result.regionID,
                                LocalName:    h.generateRegionLocalName(result.regionID),
                                IsAccessible: false,
                                LastChecked:  time.Now(),
                        }
                }</span>
        }

        <span class="cov0" title="0">close(resultChan)

        h.logger.Info("区域发现完成",
                zap.Int("总探测区域", len(regionPatterns)),
                zap.Int("可访问区域", len(validRegions)))

        return validRegions, nil</span>
}

// probeRegion 探测区域是否可访问
// 通过调用华为云ECS API来验证指定区域是否可访问
// 使用超时机制避免长时间等待
func (h *HuaweiProviderImpl) probeRegion(regionID string) bool <span class="cov8" title="1">{
        // 检查SDK服务是否已初始化
        if h.ecsService == nil </span><span class="cov8" title="1">{
                h.logger.Debug("区域探测失败：SDK未初始化", zap.String("regionId", regionID))
                return false
        }</span>

        <span class="cov0" title="0">ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
        defer cancel()

        // 尝试调用ECS API验证区域可访问性
        // 使用最小的分页参数以减少API调用开销
        _, err := h.ecsService.ListInstances(ctx, &amp;huawei.ListInstancesRequest{
                Region: regionID,
                Page:   1,
                Size:   1,
        })

        if err != nil </span><span class="cov0" title="0">{
                h.logger.Debug("区域探测失败", zap.String("regionId", regionID), zap.Error(err))
                return false
        }</span>

        <span class="cov0" title="0">return true</span>
}

// getAvailableRegionsFromSDK 通过华为云SDK获取可用区域列表
// 该方法尝试通过华为云官方API动态获取区域列表
func (h *HuaweiProviderImpl) getAvailableRegionsFromSDK() ([]string, error) <span class="cov0" title="0">{
        if h.sdk == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("SDK未初始化")
        }</span>

        // 尝试通过华为云IAM API获取区域列表
        // 华为云IAM服务提供了区域列表API
        <span class="cov0" title="0">regions, err := h.getRegionsFromIAMAPI()
        if err == nil &amp;&amp; len(regions) &gt; 0 </span><span class="cov0" title="0">{
                return regions, nil
        }</span>

        // 如果IAM API失败，尝试通过ECS API获取区域信息
        <span class="cov0" title="0">regions, err = h.getRegionsFromECSAPI()
        if err == nil &amp;&amp; len(regions) &gt; 0 </span><span class="cov0" title="0">{
                return regions, nil
        }</span>

        // 如果ECS API也失败，尝试通过VPC API获取区域信息
        <span class="cov0" title="0">regions, err = h.getRegionsFromVPCAPI()
        if err == nil &amp;&amp; len(regions) &gt; 0 </span><span class="cov0" title="0">{
                return regions, nil
        }</span>

        <span class="cov0" title="0">return nil, fmt.Errorf("无法通过华为云SDK获取区域列表")</span>
}

// getRegionsFromIAMAPI 通过华为云IAM API获取区域列表
func (h *HuaweiProviderImpl) getRegionsFromIAMAPI() ([]string, error) <span class="cov0" title="0">{
        // 检查SDK服务是否已初始化
        if h.sdk == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("SDK未初始化")
        }</span>

        // 尝试调用华为云IAM的区域列表API
        // 这里需要根据华为云SDK的实际API来实现
        // 由于华为云可能没有直接提供区域列表API，我们使用其他方法

        // 方案1：通过IAM服务的端点列表推断区域
        <span class="cov0" title="0">endpoints, err := h.getIAMEndpoints(context.Background())
        if err == nil &amp;&amp; len(endpoints) &gt; 0 </span><span class="cov0" title="0">{
                var regions []string
                for _, endpoint := range endpoints </span><span class="cov0" title="0">{
                        if region := h.extractRegionFromEndpoint(endpoint); region != "" </span><span class="cov0" title="0">{
                                regions = append(regions, region)
                        }</span>
                }
                <span class="cov0" title="0">if len(regions) &gt; 0 </span><span class="cov0" title="0">{
                        return regions, nil
                }</span>
        }

        // 由于IAM端点为空，直接返回错误，让系统使用其他方法
        <span class="cov0" title="0">return nil, fmt.Errorf("无法通过IAM API获取区域列表")</span>
}

// getRegionsFromECSAPI 通过华为云ECS API获取区域列表
func (h *HuaweiProviderImpl) getRegionsFromECSAPI() ([]string, error) <span class="cov0" title="0">{
        // 检查SDK服务是否已初始化
        if h.ecsService == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("ECS服务未初始化")
        }</span>

        // 尝试通过ECS API获取区域信息
        // 方案1：通过已知区域列表验证可访问性
        <span class="cov0" title="0">knownRegions := h.getKnownRegionPatterns()
        var accessibleRegions []string

        for _, region := range knownRegions </span><span class="cov0" title="0">{
                if h.probeRegion(region) </span><span class="cov0" title="0">{
                        accessibleRegions = append(accessibleRegions, region)
                }</span>
        }

        <span class="cov0" title="0">if len(accessibleRegions) &gt; 0 </span><span class="cov0" title="0">{
                return accessibleRegions, nil
        }</span>

        <span class="cov0" title="0">return nil, fmt.Errorf("无法通过ECS API获取区域列表")</span>
}

// getRegionsFromVPCAPI 通过华为云VPC API获取区域列表
func (h *HuaweiProviderImpl) getRegionsFromVPCAPI() ([]string, error) <span class="cov0" title="0">{
        // 检查SDK服务是否已初始化
        if h.vpcService == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("VPC服务未初始化")
        }</span>

        // 尝试通过VPC API获取区域信息
        // 方案1：通过已知区域列表验证可访问性
        <span class="cov0" title="0">knownRegions := h.getKnownRegionPatterns()
        var accessibleRegions []string

        for _, region := range knownRegions </span><span class="cov0" title="0">{
                if h.probeVPCRegion(region) </span><span class="cov0" title="0">{
                        accessibleRegions = append(accessibleRegions, region)
                }</span>
        }

        <span class="cov0" title="0">if len(accessibleRegions) &gt; 0 </span><span class="cov0" title="0">{
                return accessibleRegions, nil
        }</span>

        <span class="cov0" title="0">return nil, fmt.Errorf("无法通过VPC API获取区域列表")</span>
}

// getIAMEndpoints 获取IAM服务端点列表
func (h *HuaweiProviderImpl) getIAMEndpoints(ctx context.Context) ([]string, error) <span class="cov0" title="0">{
        // 这里应该调用华为云IAM的端点列表API
        // 由于华为云可能没有直接提供端点列表API，我们返回空数组
        // 让系统使用其他方法进行区域发现

        // 返回空数组
        return []string{}, nil
}</span>

// extractRegionFromEndpoint 从端点中提取区域信息
func (h *HuaweiProviderImpl) extractRegionFromEndpoint(endpoint string) string <span class="cov0" title="0">{
        // 华为云端点格式：service.region.myhuaweicloud.com
        parts := strings.Split(endpoint, ".")
        if len(parts) &gt;= 2 </span><span class="cov0" title="0">{
                return parts[1]
        }</span>
        <span class="cov0" title="0">return ""</span>
}

// probeVPCRegion 探测VPC区域是否可访问
func (h *HuaweiProviderImpl) probeVPCRegion(regionID string) bool <span class="cov0" title="0">{
        // 检查SDK服务是否已初始化
        if h.vpcService == nil </span><span class="cov0" title="0">{
                h.logger.Debug("VPC区域探测失败：SDK未初始化", zap.String("regionId", regionID))
                return false
        }</span>

        <span class="cov0" title="0">ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
        defer cancel()

        // 尝试调用VPC API验证区域可访问性
        // 使用最小的分页参数以减少API调用开销
        _, err := h.vpcService.ListVpcs(ctx, &amp;huawei.ListVpcsRequest{
                Region: regionID,
                Page:   1,
                Size:   1,
        })

        if err != nil </span><span class="cov0" title="0">{
                h.logger.Debug("VPC区域探测失败", zap.String("regionId", regionID), zap.Error(err))
                return false
        }</span>

        <span class="cov0" title="0">return true</span>
}

// getChineseRegionNames 获取中国区域名称
func (h *HuaweiProviderImpl) getChineseRegionNames() []string <span class="cov8" title="1">{
        // 优先从SDK动态获取中国区域名称
        if regions, err := h.getChineseRegionsFromSDK(); err == nil &amp;&amp; len(regions) &gt; 0 </span><span class="cov0" title="0">{
                return regions
        }</span>

        // 从配置中获取
        <span class="cov8" title="1">if regions := h.getChineseRegionNamesFromConfig(); len(regions) &gt; 0 </span><span class="cov0" title="0">{
                return regions
        }</span>

        // 如果都不可用，返回空数组，让调用方处理
        <span class="cov8" title="1">return []string{}</span>
}

// getChineseRegionNamesFromConfig 从配置中获取中国区域名称
func (h *HuaweiProviderImpl) getChineseRegionNamesFromConfig() []string <span class="cov8" title="1">{
        // 从环境变量读取中国区域名称配置
        if chineseRegions := os.Getenv("HUAWEI_CLOUD_CHINESE_REGIONS"); chineseRegions != "" </span><span class="cov0" title="0">{
                return strings.Split(chineseRegions, ",")
        }</span>

        // 从配置文件中读取
        <span class="cov8" title="1">if h.config != nil &amp;&amp; h.config.Discovery.EnableAutoDiscovery </span>{<span class="cov8" title="1">
                // 可以从配置中读取中国区域名称
                // 这里提供一个扩展点
        }</span>

        <span class="cov8" title="1">return []string{}</span>
}

// getChineseRegionsFromSDK 通过SDK获取中国区域名称
func (h *HuaweiProviderImpl) getChineseRegionsFromSDK() ([]string, error) <span class="cov8" title="1">{
        // 尝试通过华为云API获取中国区域信息
        // 这里可以调用华为云的区域信息API
        // 由于华为云可能没有直接提供区域名称API，我们使用其他方法

        // 方案1：通过已知区域推断区域名称
        // 从配置或环境变量中获取已知区域列表，而不是硬编码
        knownRegions := h.getKnownRegionPatterns()
        var regionNames []string

        for _, region := range knownRegions </span><span class="cov8" title="1">{
                // 只处理中国区域
                if strings.HasPrefix(region, "cn-") </span><span class="cov8" title="1">{
                        if h.probeRegion(region) </span><span class="cov0" title="0">{
                                // 从区域ID中提取区域名称
                                if name := h.extractRegionNameFromID(region); name != "" </span><span class="cov0" title="0">{
                                        regionNames = append(regionNames, name)
                                }</span>
                        }
                }
        }

        <span class="cov8" title="1">if len(regionNames) &gt; 0 </span><span class="cov0" title="0">{
                return regionNames, nil
        }</span>

        <span class="cov8" title="1">return nil, fmt.Errorf("无法通过SDK获取中国区域名称")</span>
}

// extractRegionNameFromID 从区域ID中提取区域名称
func (h *HuaweiProviderImpl) extractRegionNameFromID(regionID string) string <span class="cov0" title="0">{
        // 华为云区域ID格式：cn-{region}-{number}
        parts := strings.Split(regionID, "-")
        if len(parts) &gt;= 3 &amp;&amp; parts[0] == "cn" </span><span class="cov0" title="0">{
                return parts[1]
        }</span>
        <span class="cov0" title="0">return ""</span>
}

// getRegionNumbers 获取区域编号
func (h *HuaweiProviderImpl) getRegionNumbers() []string <span class="cov8" title="1">{
        // 优先从SDK动态获取区域编号
        if numbers, err := h.getRegionNumbersFromSDK(); err == nil &amp;&amp; len(numbers) &gt; 0 </span><span class="cov0" title="0">{
                return numbers
        }</span>

        // 从配置中获取
        <span class="cov8" title="1">if numbers := h.getRegionNumbersFromConfig(); len(numbers) &gt; 0 </span><span class="cov0" title="0">{
                return numbers
        }</span>

        // 如果都不可用，返回空数组，让调用方处理
        <span class="cov8" title="1">return []string{}</span>
}

// getRegionNumbersFromConfig 从配置中获取区域编号
func (h *HuaweiProviderImpl) getRegionNumbersFromConfig() []string <span class="cov8" title="1">{
        // 从环境变量读取区域编号配置
        if regionNumbers := os.Getenv("HUAWEI_CLOUD_REGION_NUMBERS"); regionNumbers != "" </span><span class="cov0" title="0">{
                return strings.Split(regionNumbers, ",")
        }</span>

        // 从配置文件中读取
        <span class="cov8" title="1">if h.config != nil &amp;&amp; h.config.Discovery.EnableAutoDiscovery </span>{<span class="cov8" title="1">
                // 可以从配置中读取区域编号
                // 这里提供一个扩展点
        }</span>

        <span class="cov8" title="1">return []string{}</span>
}

// getRegionNumbersFromSDK 通过SDK获取区域编号
func (h *HuaweiProviderImpl) getRegionNumbersFromSDK() ([]string, error) <span class="cov8" title="1">{
        // 尝试通过华为云API获取区域编号信息
        // 这里可以调用华为云的区域信息API
        // 由于华为云可能没有直接提供区域编号API，我们使用其他方法

        // 方案1：通过已知区域推断区域编号
        // 从配置或环境变量中获取已知区域列表，而不是硬编码
        knownRegions := h.getKnownRegionPatterns()
        var regionNumbers []string

        for _, region := range knownRegions </span><span class="cov8" title="1">{
                if h.probeRegion(region) </span><span class="cov0" title="0">{
                        // 从区域ID中提取区域编号
                        if number := h.extractRegionNumberFromID(region); number != "" </span><span class="cov0" title="0">{
                                regionNumbers = append(regionNumbers, number)
                        }</span>
                }
        }

        <span class="cov8" title="1">if len(regionNumbers) &gt; 0 </span><span class="cov0" title="0">{
                return regionNumbers, nil
        }</span>

        <span class="cov8" title="1">return nil, fmt.Errorf("无法通过SDK获取区域编号")</span>
}

// extractRegionNumberFromID 从区域ID中提取区域编号
func (h *HuaweiProviderImpl) extractRegionNumberFromID(regionID string) string <span class="cov0" title="0">{
        // 华为云区域ID格式：cn-{region}-{number}
        parts := strings.Split(regionID, "-")
        if len(parts) &gt;= 3 </span><span class="cov0" title="0">{
                return parts[2]
        }</span>
        <span class="cov0" title="0">return ""</span>
}

// getInternationalRegionPatterns 获取国际区域模式
func (h *HuaweiProviderImpl) getInternationalRegionPatterns() []string <span class="cov8" title="1">{
        // 优先从SDK动态获取国际区域
        if regions, err := h.getInternationalRegionsFromSDK(); err == nil &amp;&amp; len(regions) &gt; 0 </span><span class="cov0" title="0">{
                return regions
        }</span>

        // 从配置中获取
        <span class="cov8" title="1">if regions := h.getInternationalRegionPatternsFromConfig(); len(regions) &gt; 0 </span><span class="cov0" title="0">{
                return regions
        }</span>

        // 如果都不可用，返回空数组，让调用方处理
        <span class="cov8" title="1">return []string{}</span>
}

// getInternationalRegionPatternsFromConfig 从配置中获取国际区域模式
func (h *HuaweiProviderImpl) getInternationalRegionPatternsFromConfig() []string <span class="cov8" title="1">{
        // 从环境变量读取国际区域配置
        if internationalRegions := os.Getenv("HUAWEI_CLOUD_INTERNATIONAL_REGIONS"); internationalRegions != "" </span><span class="cov0" title="0">{
                return strings.Split(internationalRegions, ",")
        }</span>

        // 从配置文件中读取
        <span class="cov8" title="1">if h.config != nil &amp;&amp; h.config.Discovery.EnableAutoDiscovery </span>{<span class="cov8" title="1">
                // 可以从配置中读取国际区域模式
                // 这里提供一个扩展点
        }</span>

        <span class="cov8" title="1">return []string{}</span>
}

// getInternationalRegionsFromSDK 通过SDK获取国际区域
func (h *HuaweiProviderImpl) getInternationalRegionsFromSDK() ([]string, error) <span class="cov8" title="1">{
        // 尝试通过华为云API获取国际区域信息
        // 这里可以调用华为云的区域信息API
        // 由于华为云可能没有直接提供国际区域API，我们使用其他方法

        // 方案1：通过已知区域验证可访问性
        // 从配置或环境变量中获取已知区域列表，而不是硬编码
        knownRegions := h.getKnownRegionPatterns()
        var accessibleRegions []string

        for _, region := range knownRegions </span><span class="cov8" title="1">{
                // 只处理国际区域（非中国区域）
                if !strings.HasPrefix(region, "cn-") </span><span class="cov8" title="1">{
                        if h.probeRegion(region) </span><span class="cov0" title="0">{
                                accessibleRegions = append(accessibleRegions, region)
                        }</span>
                }
        }

        <span class="cov8" title="1">if len(accessibleRegions) &gt; 0 </span><span class="cov0" title="0">{
                return accessibleRegions, nil
        }</span>

        <span class="cov8" title="1">return nil, fmt.Errorf("无法通过SDK获取国际区域")</span>
}

// generateRegionPatterns 生成智能区域探测模式
// 该方法基于华为云区域命名规则生成可能的区域ID模式
// 支持动态配置和智能推测，减少硬编码依赖
func (h *HuaweiProviderImpl) generateRegionPatterns() []string <span class="cov8" title="1">{
        var patterns []string

        // 从配置中获取区域模式配置
        regionPatterns := h.getRegionPatternsFromConfig()
        if len(regionPatterns) &gt; 0 </span><span class="cov0" title="0">{
                patterns = append(patterns, regionPatterns...)
        }</span>

        // 如果配置中没有模式，使用智能推测
        <span class="cov8" title="1">if len(patterns) == 0 </span><span class="cov8" title="1">{
                patterns = h.generateSmartRegionPatterns()
        }</span>

        // 添加已知的常用区域（作为备选）
        <span class="cov8" title="1">knownRegions := h.getKnownRegionPatterns()
        patterns = append(patterns, knownRegions...)

        // 去重
        return h.deduplicatePatterns(patterns)</span>
}

// getRegionPatternsFromConfig 从配置中获取区域模式
func (h *HuaweiProviderImpl) getRegionPatternsFromConfig() []string <span class="cov8" title="1">{
        var patterns []string

        // 检查配置中是否有自定义的区域模式
        if h.config != nil &amp;&amp; h.config.Discovery.EnableAutoDiscovery </span><span class="cov8" title="1">{
                // 可以从配置文件中读取区域模式
                // 这里可以扩展为从配置文件或环境变量读取
                if customPatterns := h.getCustomRegionPatterns(); len(customPatterns) &gt; 0 </span><span class="cov0" title="0">{
                        patterns = append(patterns, customPatterns...)
                }</span>
        }

        <span class="cov8" title="1">return patterns</span>
}

// generateSmartRegionPatterns 智能生成区域模式
func (h *HuaweiProviderImpl) generateSmartRegionPatterns() []string <span class="cov8" title="1">{
        var patterns []string

        // 基于华为云区域命名规则的智能推测
        // 支持动态生成

        // 中国区域模式：cn-{region}-{number}
        cnRegions := h.getChineseRegionNames()
        cnNumbers := h.getRegionNumbers()

        for _, region := range cnRegions </span><span class="cov0" title="0">{
                for _, num := range cnNumbers </span><span class="cov0" title="0">{
                        patterns = append(patterns, fmt.Sprintf("cn-%s-%s", region, num))
                }</span>
        }

        // 亚太区域模式：ap-southeast-{number}
        <span class="cov8" title="1">apNumbers := h.getRegionNumbers()
        for _, num := range apNumbers </span><span class="cov0" title="0">{
                patterns = append(patterns, fmt.Sprintf("ap-southeast-%s", num))
        }</span>

        // 其他国际区域模式
        <span class="cov8" title="1">internationalPatterns := h.getInternationalRegionPatterns()
        patterns = append(patterns, internationalPatterns...)

        return patterns</span>
}

// getKnownRegionPatterns 获取已知的常用区域模式
func (h *HuaweiProviderImpl) getKnownRegionPatterns() []string <span class="cov8" title="1">{
        // 1. 优先通过SDK动态获取所有regionId
        if sdkRegions := h.getAllRegionsFromSDK(); len(sdkRegions) &gt; 0 </span><span class="cov0" title="0">{
                return sdkRegions
        }</span>
        // 2. 配置/环境变量兜底
        <span class="cov8" title="1">if configRegions := h.getKnownRegionsFromConfig(); len(configRegions) &gt; 0 </span><span class="cov0" title="0">{
                return configRegions
        }</span>
        // 3. 静态兜底（极端情况）
        <span class="cov8" title="1">return h.generateStaticRegionPatterns()</span>
}

// getAllRegionsFromSDK 通过SDK动态获取所有regionId（ECS/VPC API合并去重）
func (h *HuaweiProviderImpl) getAllRegionsFromSDK() []string <span class="cov8" title="1">{
        regionSet := make(map[string]struct{})
        if h.sdk != nil </span><span class="cov0" title="0">{
                if ecsRegions, err := h.getRegionsFromECSAPI(); err == nil </span><span class="cov0" title="0">{
                        for _, r := range ecsRegions </span><span class="cov0" title="0">{
                                regionSet[r] = struct{}{}
                        }</span>
                }
                <span class="cov0" title="0">if vpcRegions, err := h.getRegionsFromVPCAPI(); err == nil </span><span class="cov0" title="0">{
                        for _, r := range vpcRegions </span><span class="cov0" title="0">{
                                regionSet[r] = struct{}{}
                        }</span>
                }
        }
        <span class="cov8" title="1">var regions []string
        for r := range regionSet </span><span class="cov0" title="0">{
                regions = append(regions, r)
        }</span>
        <span class="cov8" title="1">return regions</span>
}

// generateStaticRegionPatterns 静态兜底（仅极端情况使用）
func (h *HuaweiProviderImpl) generateStaticRegionPatterns() []string <span class="cov8" title="1">{
        // 仅在SDK和配置都不可用时才用静态生成
        return []string{
                "cn-north-1", "cn-north-4", "cn-east-2", "cn-east-3", "cn-south-1",
                "ap-southeast-1", "ap-southeast-2", "ap-southeast-3",
                "eu-west-0", "eu-west-1", "eu-west-2",
                "af-south-1", "af-south-2",
                "la-south-1", "la-south-2",
                "sa-brazil-1", "sa-brazil-2",
                "na-mexico-1", "na-mexico-2",
        }
}</span>

// getKnownRegionsFromSDK 从SDK动态获取已知区域
func (h *HuaweiProviderImpl) getKnownRegionsFromSDK() []string <span class="cov0" title="0">{
        var regions []string

        // 尝试通过华为云API获取已知区域列表
        // 这里可以调用华为云的区域列表API
        if h.sdk != nil </span><span class="cov0" title="0">{
                // 尝试通过ECS API获取区域信息
                if ecsRegions, err := h.getRegionsFromECSAPI(); err == nil &amp;&amp; len(ecsRegions) &gt; 0 </span><span class="cov0" title="0">{
                        regions = append(regions, ecsRegions...)
                }</span>

                // 尝试通过VPC API获取区域信息
                <span class="cov0" title="0">if vpcRegions, err := h.getRegionsFromVPCAPI(); err == nil &amp;&amp; len(vpcRegions) &gt; 0 </span><span class="cov0" title="0">{
                        regions = append(regions, vpcRegions...)
                }</span>
        }

        <span class="cov0" title="0">return regions</span>
}

// getKnownRegionsFromConfig 从配置中获取已知区域
func (h *HuaweiProviderImpl) getKnownRegionsFromConfig() []string <span class="cov8" title="1">{
        var regions []string

        // 从环境变量读取已知区域配置
        if knownRegions := os.Getenv("HUAWEI_CLOUD_KNOWN_REGIONS"); knownRegions != "" </span><span class="cov0" title="0">{
                regions = append(regions, strings.Split(knownRegions, ",")...)
        }</span>

        // 从配置文件中读取
        <span class="cov8" title="1">if h.config != nil &amp;&amp; h.config.Discovery.EnableAutoDiscovery </span>{<span class="cov8" title="1">
                // 可以从配置中读取已知区域
                // 这里提供一个扩展点
        }</span>

        <span class="cov8" title="1">return regions</span>
}

// getCustomRegionPatterns 获取自定义区域模式
func (h *HuaweiProviderImpl) getCustomRegionPatterns() []string <span class="cov8" title="1">{
        // 可以从环境变量、配置文件或数据库读取自定义区域模式
        // 这里提供一个扩展点，可以根据实际需求实现

        // 示例：从环境变量读取
        if customPatterns := os.Getenv("HUAWEI_CLOUD_CUSTOM_REGIONS"); customPatterns != "" </span><span class="cov0" title="0">{
                return strings.Split(customPatterns, ",")
        }</span>

        <span class="cov8" title="1">return []string{}</span>
}

// deduplicatePatterns 去重区域模式
func (h *HuaweiProviderImpl) deduplicatePatterns(patterns []string) []string <span class="cov8" title="1">{
        seen := make(map[string]bool)
        var result []string

        for _, pattern := range patterns </span><span class="cov8" title="1">{
                if !seen[pattern] </span><span class="cov8" title="1">{
                        seen[pattern] = true
                        result = append(result, pattern)
                }</span>
        }

        <span class="cov8" title="1">return result</span>
}

// generateRegionLocalName 生成区域的本地化名称
// 该方法尝试从缓存中获取区域名称，如果不存在则通过API动态获取
// 支持智能缓存机制，避免重复的API调用
func (h *HuaweiProviderImpl) generateRegionLocalName(regionID string) string <span class="cov8" title="1">{
        // 尝试从已发现的区域信息中获取本地化名称
        // 优先使用缓存中的信息以提高性能
        if regionInfo, exists := h.discoveredRegions[regionID]; exists &amp;&amp; regionInfo.LocalName != "" </span><span class="cov0" title="0">{
                return regionInfo.LocalName
        }</span>

        // 如果还没有发现该区域，尝试通过API获取区域信息
        <span class="cov8" title="1">if h.sdk != nil </span><span class="cov0" title="0">{
                localName, err := h.getRegionLocalNameFromAPI(regionID)
                if err == nil &amp;&amp; localName != "" </span><span class="cov0" title="0">{
                        // 更新发现的区域信息到缓存
                        if h.discoveredRegions[regionID] == nil </span><span class="cov0" title="0">{
                                h.discoveredRegions[regionID] = &amp;HuaweiRegionInfo{
                                        RegionID:     regionID,
                                        IsAccessible: true,
                                        LastChecked:  time.Now(),
                                }
                        }</span>
                        <span class="cov0" title="0">h.discoveredRegions[regionID].LocalName = localName
                        return localName</span>
                }
        }

        // 如果无法获取区域信息，返回区域ID作为默认名称
        <span class="cov8" title="1">return regionID</span>
}

// getRegionLocalNameFromAPI 通过华为云SDK获取区域本地化名称
// 该方法通过调用华为云API来获取区域的详细信息
// 如果华为云提供了区域名称API，应该在此方法中实现
func (h *HuaweiProviderImpl) getRegionLocalNameFromAPI(regionID string) (string, error) <span class="cov0" title="0">{
        if h.sdk == nil </span><span class="cov0" title="0">{
                return "", fmt.Errorf("SDK未初始化")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov0" title="0">if h.ecsService == nil </span><span class="cov0" title="0">{
                return "", fmt.Errorf("ECS服务未初始化")
        }</span>

        <span class="cov0" title="0">ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
        defer cancel()

        // 通过ECS API验证区域可访问性
        // 这是一个轻量级的API调用来确认区域存在
        _, err := h.ecsService.ListInstances(ctx, &amp;huawei.ListInstancesRequest{
                Region: regionID,
                Page:   1,
                Size:   1,
        })

        if err != nil </span><span class="cov0" title="0">{
                return "", fmt.Errorf("无法访问区域 %s: %w", regionID, err)
        }</span>

        // 通过华为云IAM API获取区域详细信息
        // 这里可以调用华为云IAM的区域列表API来获取区域的中文名称
        // 由于华为云可能没有直接提供区域名称的API，我们使用区域ID作为基础名称
        // 在实际应用中，可以根据需要调用其他华为云API来获取更详细的区域信息

        <span class="cov0" title="0">return fmt.Sprintf("区域-%s", regionID), nil</span>
}

// getKnownRegions 从发现的区域map中获取区域信息
func (h *HuaweiProviderImpl) getKnownRegions() []HuaweiRegionInfo <span class="cov0" title="0">{
        var regions []HuaweiRegionInfo

        for _, regionInfo := range h.discoveredRegions </span><span class="cov0" title="0">{
                if regionInfo.IsAccessible </span><span class="cov0" title="0">{
                        regions = append(regions, HuaweiRegionInfo{
                                RegionID:  regionInfo.RegionID,
                                LocalName: regionInfo.LocalName,
                        })
                }</span>
        }

        <span class="cov0" title="0">return regions</span>
}

func (h *HuaweiProviderImpl) GetZonesByVpc(ctx context.Context, region string, vpcId string) ([]*model.ZoneResp, error) <span class="cov0" title="0">{
        if region == "" || vpcId == "" </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("region and vpcId cannot be empty")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov0" title="0">if h.vpcService == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">h.logger.Debug("开始获取VPC可用区", zap.String("region", region), zap.String("vpcId", vpcId))

        // 获取VPC详情
        vpcDetail, err := h.vpcService.GetVpcDetail(ctx, region, vpcId)
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("获取VPC详情失败", zap.Error(err), zap.String("vpcId", vpcId))
                return nil, fmt.Errorf("获取VPC详情失败: %w", err)
        }</span>

        <span class="cov0" title="0">if vpcDetail == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("VPC不存在: %s", vpcId)
        }</span>

        // 获取VPC下的子网列表
        <span class="cov0" title="0">subnets, err := h.getSubnetsByVpc(ctx, region, vpcId)
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("获取VPC子网列表失败", zap.Error(err), zap.String("vpcId", vpcId))
                return nil, fmt.Errorf("获取VPC子网列表失败: %w", err)
        }</span>

        // 从子网中提取可用区信息
        <span class="cov0" title="0">zoneMap := make(map[string]*model.ZoneResp)
        for _, subnet := range subnets </span><span class="cov0" title="0">{
                if subnet.ZoneId != "" </span><span class="cov0" title="0">{
                        zoneMap[subnet.ZoneId] = &amp;model.ZoneResp{
                                ZoneId:    subnet.ZoneId,
                                LocalName: h.generateZoneLocalName(subnet.ZoneId),
                        }
                }</span>
        }

        // 转换为切片
        <span class="cov0" title="0">var zones []*model.ZoneResp
        for _, zone := range zoneMap </span><span class="cov0" title="0">{
                zones = append(zones, zone)
        }</span>

        <span class="cov0" title="0">h.logger.Info("获取VPC可用区成功",
                zap.String("vpcId", vpcId),
                zap.Int("zoneCount", len(zones)),
                zap.String("region", region))

        return zones, nil</span>
}

// getSubnetsByVpc 获取VPC下的子网列表
func (h *HuaweiProviderImpl) getSubnetsByVpc(ctx context.Context, region string, vpcId string) ([]*model.ResourceSubnet, error) <span class="cov0" title="0">{
        // 这里需要调用华为云SDK的子网列表API
        // 由于华为云SDK可能没有直接提供子网列表方法，我们使用VPC详情中的信息

        // 获取VPC详情
        vpcDetail, err := h.vpcService.GetVpcDetail(ctx, region, vpcId)
        if err != nil </span><span class="cov0" title="0">{
                return nil, err
        }</span>

        <span class="cov0" title="0">var subnets []*model.ResourceSubnet

        // 从VPC的CloudResources中提取子网信息
        if vpcDetail.CloudResources != nil </span><span class="cov0" title="0">{
                for _, resource := range vpcDetail.CloudResources </span><span class="cov0" title="0">{
                        if resource.ResourceType == "virsubnet" </span><span class="cov0" title="0">{
                                // 这里需要进一步查询子网详情
                                // 暂时返回基本信息
                                subnet := &amp;model.ResourceSubnet{
                                        VpcId:    vpcId,
                                        Provider: model.CloudProviderHuawei,
                                        RegionId: region,
                                        Status:   "Available", // 假设子网可用
                                }
                                subnets = append(subnets, subnet)
                        }</span>
                }
        }

        <span class="cov0" title="0">return subnets, nil</span>
}

// generateZoneLocalName 生成可用区的本地化名称
func (h *HuaweiProviderImpl) generateZoneLocalName(zoneId string) string <span class="cov0" title="0">{
        // 华为云可用区命名规则：region-az，如 cn-north-4-01
        // 提取可用区编号作为显示名称
        if len(zoneId) &gt;= 2 </span><span class="cov0" title="0">{
                parts := strings.Split(zoneId, "-")
                if len(parts) &gt;= 4 </span><span class="cov0" title="0">{
                        // 返回可用区编号，如 "01"
                        return parts[len(parts)-1]
                }</span>
        }
        <span class="cov0" title="0">return zoneId</span>
}

// ECS实例管理
func (h *HuaweiProviderImpl) ListInstances(ctx context.Context, region string, page, size int) ([]*model.ResourceEcs, int64, error) <span class="cov8" title="1">{
        if region == "" </span><span class="cov0" title="0">{
                return nil, 0, fmt.Errorf("region cannot be empty")
        }</span>
        <span class="cov8" title="1">if page &lt;= 0 || size &lt;= 0 </span><span class="cov0" title="0">{
                return nil, 0, fmt.Errorf("page and size must be positive integers")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov8" title="1">if h.ecsService == nil </span><span class="cov8" title="1">{
                return nil, 0, fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">req := &amp;huawei.ListInstancesRequest{
                Region: region,
                Page:   page,
                Size:   size,
        }

        resp, err := h.ecsService.ListInstances(ctx, req)
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("failed to list instances", zap.Error(err), zap.String("region", region))
                return nil, 0, fmt.Errorf("list instances failed: %w", err)
        }</span>

        <span class="cov0" title="0">if resp == nil || len(resp.Instances) == 0 </span><span class="cov0" title="0">{
                return nil, 0, nil
        }</span>

        <span class="cov0" title="0">result := make([]*model.ResourceEcs, 0, len(resp.Instances))
        for _, instance := range resp.Instances </span><span class="cov0" title="0">{
                result = append(result, h.convertToResourceEcsFromListInstance(instance))
        }</span>

        <span class="cov0" title="0">return result, int64(resp.Total), nil</span>
}

func (h *HuaweiProviderImpl) GetInstance(ctx context.Context, region string, instanceID string) (*model.ResourceEcs, error) <span class="cov0" title="0">{
        if region == "" || instanceID == "" </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("region and instanceID cannot be empty")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov0" title="0">if h.ecsService == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">instance, err := h.ecsService.GetInstanceDetail(ctx, region, instanceID)
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("failed to get instance detail", zap.Error(err), zap.String("instanceID", instanceID))
                return nil, fmt.Errorf("get instance detail failed: %w", err)
        }</span>

        <span class="cov0" title="0">if instance == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("instance not found")
        }</span>

        <span class="cov0" title="0">return h.convertToResourceEcsFromInstanceDetail(instance), nil</span>
}

func (h *HuaweiProviderImpl) CreateInstance(ctx context.Context, region string, config *model.CreateEcsResourceReq) error <span class="cov0" title="0">{
        if region == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region cannot be empty")
        }</span>
        <span class="cov0" title="0">if config == nil </span><span class="cov0" title="0">{
                return fmt.Errorf("config cannot be nil")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov0" title="0">if h.ecsService == nil </span><span class="cov0" title="0">{
                return fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">req := &amp;huawei.CreateInstanceRequest{
                Region:             region,
                ZoneId:             config.ZoneId,
                ImageId:            config.ImageId,
                InstanceType:       config.InstanceType,
                SecurityGroupIds:   config.SecurityGroupIds,
                SubnetId:           config.VSwitchId, // 华为云使用SubnetId而不是VSwitchId
                InstanceName:       config.InstanceName,
                Hostname:           config.Hostname,
                Password:           config.Password,
                Description:        config.Description,
                Amount:             config.Amount,
                DryRun:             config.DryRun,
                InstanceChargeType: h.getInstanceChargeType(config.InstanceChargeType),
                SystemDiskCategory: config.SystemDiskCategory,
                SystemDiskSize:     config.SystemDiskSize,
                DataDiskCategory:   config.DataDiskCategory,
                DataDiskSize:       config.DataDiskSize,
        }

        _, err := h.ecsService.CreateInstance(ctx, req)
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("failed to create instance", zap.Error(err), zap.String("region", region))
                return fmt.Errorf("create instance failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

func (h *HuaweiProviderImpl) DeleteInstance(ctx context.Context, region string, instanceID string) error <span class="cov0" title="0">{
        if region == "" || instanceID == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region and instanceID cannot be empty")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov0" title="0">if h.ecsService == nil </span><span class="cov0" title="0">{
                return fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">err := h.ecsService.DeleteInstance(ctx, region, instanceID, h.config.Defaults.ForceDelete)
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("failed to delete instance", zap.Error(err), zap.String("instanceID", instanceID))
                return fmt.Errorf("delete instance failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

func (h *HuaweiProviderImpl) StartInstance(ctx context.Context, region string, instanceID string) error <span class="cov0" title="0">{
        if region == "" || instanceID == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region and instanceID cannot be empty")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov0" title="0">if h.ecsService == nil </span><span class="cov0" title="0">{
                return fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">err := h.ecsService.StartInstance(ctx, region, instanceID)
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("failed to start instance", zap.Error(err), zap.String("instanceID", instanceID))
                return fmt.Errorf("start instance failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

func (h *HuaweiProviderImpl) StopInstance(ctx context.Context, region string, instanceID string) error <span class="cov0" title="0">{
        if region == "" || instanceID == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region and instanceID cannot be empty")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov0" title="0">if h.ecsService == nil </span><span class="cov0" title="0">{
                return fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">err := h.ecsService.StopInstance(ctx, region, instanceID, h.config.Defaults.ForceStop)
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("failed to stop instance", zap.Error(err), zap.String("instanceID", instanceID))
                return fmt.Errorf("stop instance failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

func (h *HuaweiProviderImpl) RestartInstance(ctx context.Context, region string, instanceID string) error <span class="cov0" title="0">{
        if region == "" || instanceID == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region and instanceID cannot be empty")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov0" title="0">if h.ecsService == nil </span><span class="cov0" title="0">{
                return fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">err := h.ecsService.RestartInstance(ctx, region, instanceID)
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("failed to restart instance", zap.Error(err), zap.String("instanceID", instanceID))
                return fmt.Errorf("restart instance failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

// VPC网络管理
func (h *HuaweiProviderImpl) ListVPCs(ctx context.Context, region string, pageNumber, pageSize int) ([]*model.ResourceVpc, error) <span class="cov8" title="1">{
        if region == "" </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("region cannot be empty")
        }</span>
        <span class="cov8" title="1">if pageNumber &lt;= 0 || pageSize &lt;= 0 </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("pageNumber and pageSize must be positive integers")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov8" title="1">if h.vpcService == nil </span><span class="cov8" title="1">{
                return nil, fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">req := &amp;huawei.ListVpcsRequest{
                Region: region,
                Page:   pageNumber,
                Size:   pageSize,
        }

        resp, err := h.vpcService.ListVpcs(ctx, req)
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("failed to list VPCs", zap.Error(err), zap.String("region", region))
                return nil, fmt.Errorf("list VPCs failed: %w", err)
        }</span>

        <span class="cov0" title="0">if resp == nil || len(resp.Vpcs) == 0 </span><span class="cov0" title="0">{
                return nil, nil
        }</span>

        <span class="cov0" title="0">result := make([]*model.ResourceVpc, 0, len(resp.Vpcs))
        for _, vpcData := range resp.Vpcs </span><span class="cov0" title="0">{
                result = append(result, h.convertToResourceVpcFromListVpc(vpcData, region))
        }</span>

        <span class="cov0" title="0">return result, nil</span>
}

func (h *HuaweiProviderImpl) GetVPC(ctx context.Context, region string, vpcID string) (*model.ResourceVpc, error) <span class="cov0" title="0">{
        if region == "" || vpcID == "" </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("region and vpcID cannot be empty")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov0" title="0">if h.vpcService == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">vpcDetail, err := h.vpcService.GetVpcDetail(ctx, region, vpcID)
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("failed to get VPC detail", zap.Error(err), zap.String("vpcID", vpcID))
                return nil, fmt.Errorf("get VPC detail failed: %w", err)
        }</span>

        <span class="cov0" title="0">if vpcDetail == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("VPC not found")
        }</span>

        <span class="cov0" title="0">return h.convertToResourceVpcFromDetail(vpcDetail, region), nil</span>
}

func (h *HuaweiProviderImpl) CreateVPC(ctx context.Context, region string, config *model.CreateVpcResourceReq) error <span class="cov0" title="0">{
        if region == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region cannot be empty")
        }</span>
        <span class="cov0" title="0">if config == nil </span><span class="cov0" title="0">{
                return fmt.Errorf("config cannot be nil")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov0" title="0">if h.vpcService == nil </span><span class="cov0" title="0">{
                return fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">req := &amp;huawei.CreateVpcRequest{
                Region:          region,
                VpcName:         config.VpcName,
                CidrBlock:       config.CidrBlock,
                Description:     config.Description,
                ZoneId:          config.ZoneId,
                SubnetName:      config.VSwitchName,      // 华为云使用SubnetName
                SubnetCidrBlock: config.VSwitchCidrBlock, // 华为云使用SubnetCidrBlock
        }

        _, err := h.vpcService.CreateVPC(ctx, req)
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("failed to create VPC", zap.Error(err), zap.String("region", region))
                return fmt.Errorf("create VPC failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

func (h *HuaweiProviderImpl) DeleteVPC(ctx context.Context, region string, vpcID string) error <span class="cov0" title="0">{
        if region == "" || vpcID == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region and vpcID cannot be empty")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov0" title="0">if h.vpcService == nil </span><span class="cov0" title="0">{
                return fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">err := h.vpcService.DeleteVPC(ctx, region, vpcID)
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("failed to delete VPC", zap.Error(err), zap.String("vpcID", vpcID))
                return fmt.Errorf("delete VPC failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

// 安全组管理
func (h *HuaweiProviderImpl) ListSecurityGroups(ctx context.Context, region string, pageNumber, pageSize int) ([]*model.ResourceSecurityGroup, error) <span class="cov8" title="1">{
        if region == "" </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("region cannot be empty")
        }</span>
        <span class="cov8" title="1">if pageNumber &lt;= 0 || pageSize &lt;= 0 </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("pageNumber and pageSize must be positive integers")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov8" title="1">if h.securityGroupService == nil </span><span class="cov8" title="1">{
                return nil, fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">req := &amp;huawei.ListSecurityGroupsRequest{
                Region:     region,
                PageNumber: pageNumber,
                PageSize:   pageSize,
        }

        resp, err := h.securityGroupService.ListSecurityGroups(ctx, req)
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("failed to list security groups", zap.Error(err), zap.String("region", region))
                return nil, fmt.Errorf("list security groups failed: %w", err)
        }</span>

        <span class="cov0" title="0">if resp == nil || len(resp.SecurityGroups) == 0 </span><span class="cov0" title="0">{
                return nil, nil
        }</span>

        <span class="cov0" title="0">result := make([]*model.ResourceSecurityGroup, 0, len(resp.SecurityGroups))
        for _, sg := range resp.SecurityGroups </span><span class="cov0" title="0">{
                result = append(result, h.convertToResourceSecurityGroupFromList(sg, region))
        }</span>

        <span class="cov0" title="0">return result, nil</span>
}

func (h *HuaweiProviderImpl) GetSecurityGroup(ctx context.Context, region string, securityGroupID string) (*model.ResourceSecurityGroup, error) <span class="cov0" title="0">{
        if region == "" || securityGroupID == "" </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("region and securityGroupID cannot be empty")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov0" title="0">if h.securityGroupService == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">sg, err := h.securityGroupService.GetSecurityGroupDetail(ctx, region, securityGroupID)
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("failed to get security group detail", zap.Error(err), zap.String("securityGroupID", securityGroupID))
                return nil, fmt.Errorf("get security group detail failed: %w", err)
        }</span>

        <span class="cov0" title="0">if sg == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("security group not found")
        }</span>

        <span class="cov0" title="0">return h.convertToResourceSecurityGroupFromDetail(sg, region), nil</span>
}

func (h *HuaweiProviderImpl) CreateSecurityGroup(ctx context.Context, region string, config *model.CreateSecurityGroupReq) error <span class="cov0" title="0">{
        if region == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region cannot be empty")
        }</span>
        <span class="cov0" title="0">if config == nil </span><span class="cov0" title="0">{
                return fmt.Errorf("config cannot be nil")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov0" title="0">if h.securityGroupService == nil </span><span class="cov0" title="0">{
                return fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">req := &amp;huawei.CreateSecurityGroupRequest{
                Region:            region,
                SecurityGroupName: config.SecurityGroupName,
                Description:       config.Description,
                VpcId:             config.VpcId,
                SecurityGroupType: config.SecurityGroupType,
                ResourceGroupId:   config.ResourceGroupId,
                Tags:              config.Tags,
        }

        _, err := h.securityGroupService.CreateSecurityGroup(ctx, req)
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("failed to create security group", zap.Error(err), zap.String("region", region))
                return fmt.Errorf("create security group failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

func (h *HuaweiProviderImpl) DeleteSecurityGroup(ctx context.Context, region string, securityGroupID string) error <span class="cov0" title="0">{
        if region == "" || securityGroupID == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region and securityGroupID cannot be empty")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov0" title="0">if h.securityGroupService == nil </span><span class="cov0" title="0">{
                return fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">err := h.securityGroupService.DeleteSecurityGroup(ctx, region, securityGroupID)
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("failed to delete security group", zap.Error(err), zap.String("securityGroupID", securityGroupID))
                return fmt.Errorf("delete security group failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

// 磁盘管理
func (h *HuaweiProviderImpl) ListDisks(ctx context.Context, region string, pageNumber, pageSize int) ([]*model.ResourceDisk, error) <span class="cov8" title="1">{
        if region == "" </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("region cannot be empty")
        }</span>
        <span class="cov8" title="1">if pageNumber &lt;= 0 || pageSize &lt;= 0 </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("pageNumber and pageSize must be positive integers")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov8" title="1">if h.diskService == nil </span><span class="cov8" title="1">{
                return nil, fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">req := &amp;huawei.ListDisksRequest{
                Region: region,
                Page:   pageNumber,
                Size:   pageSize,
        }

        resp, err := h.diskService.ListDisks(ctx, req)
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("failed to list disks", zap.Error(err), zap.String("region", region))
                return nil, fmt.Errorf("list disks failed: %w", err)
        }</span>

        <span class="cov0" title="0">if resp == nil || len(resp.Disks) == 0 </span><span class="cov0" title="0">{
                return nil, nil
        }</span>

        <span class="cov0" title="0">result := make([]*model.ResourceDisk, 0, len(resp.Disks))
        for _, disk := range resp.Disks </span><span class="cov0" title="0">{
                result = append(result, h.convertToResourceDiskFromList(disk, region))
        }</span>

        <span class="cov0" title="0">return result, nil</span>
}

func (h *HuaweiProviderImpl) GetDisk(ctx context.Context, region string, diskID string) (*model.ResourceDisk, error) <span class="cov0" title="0">{
        if region == "" || diskID == "" </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("region and diskID cannot be empty")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov0" title="0">if h.diskService == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">disk, err := h.diskService.GetDisk(ctx, region, diskID)
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("failed to get disk detail", zap.Error(err), zap.String("diskID", diskID))
                return nil, fmt.Errorf("get disk detail failed: %w", err)
        }</span>

        <span class="cov0" title="0">if disk == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("disk not found")
        }</span>

        <span class="cov0" title="0">return h.convertToResourceDiskFromDetail(disk, region), nil</span>
}

func (h *HuaweiProviderImpl) CreateDisk(ctx context.Context, region string, config *model.CreateDiskReq) error <span class="cov0" title="0">{
        if region == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region cannot be empty")
        }</span>
        <span class="cov0" title="0">if config == nil </span><span class="cov0" title="0">{
                return fmt.Errorf("config cannot be nil")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov0" title="0">if h.diskService == nil </span><span class="cov0" title="0">{
                return fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">req := &amp;huawei.CreateDiskRequest{
                Region:       region,
                ZoneId:       config.ZoneId,
                DiskName:     config.DiskName,
                DiskCategory: config.DiskCategory,
                Size:         config.Size,
                Description:  config.Description,
        }

        _, err := h.diskService.CreateDisk(ctx, req)
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("failed to create disk", zap.Error(err), zap.String("region", region))
                return fmt.Errorf("create disk failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

func (h *HuaweiProviderImpl) DeleteDisk(ctx context.Context, region string, diskID string) error <span class="cov0" title="0">{
        if region == "" || diskID == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region and diskID cannot be empty")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov0" title="0">if h.diskService == nil </span><span class="cov0" title="0">{
                return fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">err := h.diskService.DeleteDisk(ctx, region, diskID)
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("failed to delete disk", zap.Error(err), zap.String("diskID", diskID))
                return fmt.Errorf("delete disk failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

// AttachDisk 挂载磁盘
func (h *HuaweiProviderImpl) AttachDisk(ctx context.Context, region string, diskID, instanceID string) error <span class="cov0" title="0">{
        if region == "" || diskID == "" || instanceID == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region, diskID and instanceID cannot be empty")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov0" title="0">if h.diskService == nil </span><span class="cov0" title="0">{
                return fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">err := h.diskService.AttachDisk(ctx, region, diskID, instanceID)
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("failed to attach disk", zap.Error(err), zap.String("diskID", diskID), zap.String("instanceID", instanceID))
                return fmt.Errorf("attach disk failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

func (h *HuaweiProviderImpl) DetachDisk(ctx context.Context, region string, diskID, instanceID string) error <span class="cov0" title="0">{
        if region == "" || diskID == "" || instanceID == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("region, diskID and instanceID cannot be empty")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov0" title="0">if h.diskService == nil </span><span class="cov0" title="0">{
                return fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">err := h.diskService.DetachDisk(ctx, region, diskID, instanceID)
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("failed to detach disk", zap.Error(err), zap.String("diskID", diskID), zap.String("instanceID", instanceID))
                return fmt.Errorf("detach disk failed: %w", err)
        }</span>

        <span class="cov0" title="0">return nil</span>
}

// 资源选项查询方法
func (h *HuaweiProviderImpl) ListRegionOptions(ctx context.Context) ([]*model.ListEcsResourceOptionsResp, error) <span class="cov0" title="0">{
        // 检查SDK服务是否已初始化
        if h.sdk == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">h.logger.Debug("开始查询区域选项")

        // 获取区域列表
        regions, err := h.ListRegions(ctx)
        if err != nil </span><span class="cov0" title="0">{
                h.logger.Error("获取区域列表失败", zap.Error(err))
                return nil, fmt.Errorf("获取区域列表失败: %w", err)
        }</span>

        <span class="cov0" title="0">var options []*model.ListEcsResourceOptionsResp
        for _, region := range regions </span><span class="cov0" title="0">{
                option := &amp;model.ListEcsResourceOptionsResp{
                        Value:  region.RegionId,
                        Label:  region.LocalName,
                        Region: region.RegionId,
                        Valid:  true,
                }
                options = append(options, option)
        }</span>

        <span class="cov0" title="0">h.logger.Info("区域选项查询完成", zap.Int("count", len(options)))
        return options, nil</span>
}

func (h *HuaweiProviderImpl) ListRegionZones(ctx context.Context, region string) ([]*model.ListEcsResourceOptionsResp, error) <span class="cov0" title="0">{
        if region == "" </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("region cannot be empty")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov0" title="0">if h.ecsService == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">h.logger.Debug("开始查询区域可用区", zap.String("region", region))

        // 华为云ECS服务通常提供可用区列表API
        // 这里我们使用预定义的可用区列表，实际应用中应该调用API
        zoneOptions := h.getAvailableZones(region)

        var options []*model.ListEcsResourceOptionsResp
        for _, zone := range zoneOptions </span><span class="cov0" title="0">{
                option := &amp;model.ListEcsResourceOptionsResp{
                        Value:  zone.ZoneId,
                        Label:  zone.LocalName,
                        Region: region,
                        Zone:   zone.ZoneId,
                        Valid:  true,
                }
                options = append(options, option)
        }</span>

        <span class="cov0" title="0">h.logger.Info("区域可用区查询完成", zap.String("region", region), zap.Int("count", len(options)))
        return options, nil</span>
}

func (h *HuaweiProviderImpl) ListRegionInstanceTypes(ctx context.Context, region string) ([]*model.ListEcsResourceOptionsResp, error) <span class="cov0" title="0">{
        if region == "" </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("region cannot be empty")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov0" title="0">if h.ecsService == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">h.logger.Debug("开始查询实例类型", zap.String("region", region))

        // 华为云ECS服务提供实例类型列表API
        // 这里我们使用预定义的实例类型列表，实际应用中应该调用API
        instanceTypes := h.getAvailableInstanceTypes(region)

        var options []*model.ListEcsResourceOptionsResp
        for _, instanceType := range instanceTypes </span><span class="cov0" title="0">{
                option := &amp;model.ListEcsResourceOptionsResp{
                        Value:        instanceType.InstanceTypeId,
                        Label:        instanceType.Description,
                        Region:       region,
                        InstanceType: instanceType.InstanceTypeId,
                        Cpu:          instanceType.CpuCoreCount,
                        Memory:       instanceType.MemorySize,
                        Valid:        true,
                }
                options = append(options, option)
        }</span>

        <span class="cov0" title="0">h.logger.Info("实例类型查询完成", zap.String("region", region), zap.Int("count", len(options)))
        return options, nil</span>
}

func (h *HuaweiProviderImpl) ListRegionImages(ctx context.Context, region string) ([]*model.ListEcsResourceOptionsResp, error) <span class="cov0" title="0">{
        if region == "" </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("region cannot be empty")
        }</span>

        // 检查SDK服务是否已初始化
        <span class="cov0" title="0">if h.ecsService == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("华为云SDK未初始化，请先调用InitializeProvider")
        }</span>

        <span class="cov0" title="0">h.logger.Debug("开始查询镜像", zap.String("region", region))

        // 华为云ECS服务提供镜像列表API
        // 这里我们使用预定义的镜像列表，实际应用中应该调用API
        images := h.getAvailableImages(region)

        var options []*model.ListEcsResourceOptionsResp
        for _, image := range images </span><span class="cov0" title="0">{
                option := &amp;model.ListEcsResourceOptionsResp{
                        Value:   image.ImageId,
                        Label:   image.ImageName,
                        Region:  region,
                        ImageId: image.ImageId,
                        OSName:  image.ImageName,
                        OSType:  image.OSType,
                        Valid:   true,
                }
                options = append(options, option)
        }</span>

        <span class="cov0" title="0">h.logger.Info("镜像查询完成", zap.String("region", region), zap.Int("count", len(options)))
        return options, nil</span>
}

func (h *HuaweiProviderImpl) ListRegionSystemDiskCategories(ctx context.Context, region string) ([]*model.ListEcsResourceOptionsResp, error) <span class="cov0" title="0">{
        if region == "" </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("region cannot be empty")
        }</span>

        <span class="cov0" title="0">h.logger.Debug("开始查询系统盘类型", zap.String("region", region))

        // 华为云系统盘类型
        systemDiskTypes := []string{
                "SSD",    // 超高IO云硬盘
                "GPSSD",  // 通用型SSD云硬盘
                "SAS",    // 高IO云硬盘
                "SATA",   // 普通IO云硬盘
                "ESSD",   // 极速IO云硬盘
                "GPSSD2", // 通用型SSD V2云硬盘
                "ESSD2",  // 极速IO V2云硬盘
        }

        var options []*model.ListEcsResourceOptionsResp
        for _, diskType := range systemDiskTypes </span><span class="cov0" title="0">{
                option := &amp;model.ListEcsResourceOptionsResp{
                        Value:              diskType,
                        Label:              h.getDiskTypeDescription(diskType),
                        Region:             region,
                        SystemDiskCategory: diskType,
                        Valid:              true,
                }
                options = append(options, option)
        }</span>

        <span class="cov0" title="0">h.logger.Info("系统盘类型查询完成", zap.String("region", region), zap.Int("count", len(options)))
        return options, nil</span>
}

func (h *HuaweiProviderImpl) ListRegionDataDiskCategories(ctx context.Context, region string) ([]*model.ListEcsResourceOptionsResp, error) <span class="cov0" title="0">{
        if region == "" </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("region cannot be empty")
        }</span>

        <span class="cov0" title="0">h.logger.Debug("开始查询数据盘类型", zap.String("region", region))

        // 华为云数据盘类型（与系统盘类型相同）
        dataDiskTypes := []string{
                "SSD",    // 超高IO云硬盘
                "GPSSD",  // 通用型SSD云硬盘
                "SAS",    // 高IO云硬盘
                "SATA",   // 普通IO云硬盘
                "ESSD",   // 极速IO云硬盘
                "GPSSD2", // 通用型SSD V2云硬盘
                "ESSD2",  // 极速IO V2云硬盘
        }

        var options []*model.ListEcsResourceOptionsResp
        for _, diskType := range dataDiskTypes </span><span class="cov0" title="0">{
                option := &amp;model.ListEcsResourceOptionsResp{
                        Value:            diskType,
                        Label:            h.getDiskTypeDescription(diskType),
                        Region:           region,
                        DataDiskCategory: diskType,
                        Valid:            true,
                }
                options = append(options, option)
        }</span>

        <span class="cov0" title="0">h.logger.Info("数据盘类型查询完成", zap.String("region", region), zap.Int("count", len(options)))
        return options, nil</span>
}

// getAvailableZones 获取可用区列表
func (h *HuaweiProviderImpl) getAvailableZones(region string) []*model.ZoneResp <span class="cov0" title="0">{
        // 优先尝试通过API动态获取可用区
        if zones, err := h.getZonesFromAPI(region); err == nil &amp;&amp; len(zones) &gt; 0 </span><span class="cov0" title="0">{
                return zones
        }</span>

        // 如果API获取失败，使用智能生成
        <span class="cov0" title="0">return h.generateZonesForRegion(region)</span>
}

// getZonesFromAPI 通过API获取可用区列表
func (h *HuaweiProviderImpl) getZonesFromAPI(region string) ([]*model.ZoneResp, error) <span class="cov0" title="0">{
        // 检查SDK服务是否已初始化
        if h.ecsService == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("ECS服务未初始化")
        }</span>

        <span class="cov0" title="0">ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
        defer cancel()

        // 尝试通过ECS API获取可用区列表
        // 这里可以调用华为云ECS的可用区列表API
        // 由于华为云可能没有直接提供可用区列表API，我们使用其他方法

        // 方案1：通过实例列表推断可用区
        instances, _, err := h.ListInstances(ctx, region, 1, 100)
        if err == nil &amp;&amp; len(instances) &gt; 0 </span><span class="cov0" title="0">{
                zoneMap := make(map[string]*model.ZoneResp)
                for _, instance := range instances </span><span class="cov0" title="0">{
                        if instance.ZoneId != "" </span><span class="cov0" title="0">{
                                zoneMap[instance.ZoneId] = &amp;model.ZoneResp{
                                        ZoneId:    instance.ZoneId,
                                        LocalName: h.generateZoneLocalName(instance.ZoneId),
                                }
                        }</span>
                }

                <span class="cov0" title="0">var zones []*model.ZoneResp
                for _, zone := range zoneMap </span><span class="cov0" title="0">{
                        zones = append(zones, zone)
                }</span>

                <span class="cov0" title="0">if len(zones) &gt; 0 </span><span class="cov0" title="0">{
                        return zones, nil
                }</span>
        }

        // 方案2：通过VPC列表推断可用区
        <span class="cov0" title="0">vpcs, err := h.ListVPCs(ctx, region, 1, 100)
        if err == nil &amp;&amp; len(vpcs) &gt; 0 </span><span class="cov0" title="0">{
                zoneMap := make(map[string]*model.ZoneResp)
                for _, vpc := range vpcs </span><span class="cov0" title="0">{
                        if vpcZones, err := h.GetZonesByVpc(ctx, region, vpc.VpcId); err == nil </span><span class="cov0" title="0">{
                                for _, zone := range vpcZones </span><span class="cov0" title="0">{
                                        zoneMap[zone.ZoneId] = zone
                                }</span>
                        }
                }

                <span class="cov0" title="0">var zones []*model.ZoneResp
                for _, zone := range zoneMap </span><span class="cov0" title="0">{
                        zones = append(zones, zone)
                }</span>

                <span class="cov0" title="0">if len(zones) &gt; 0 </span><span class="cov0" title="0">{
                        return zones, nil
                }</span>
        }

        <span class="cov0" title="0">return nil, fmt.Errorf("无法通过API获取可用区列表")</span>
}

// generateZonesForRegion 为指定区域智能生成可用区
func (h *HuaweiProviderImpl) generateZonesForRegion(region string) []*model.ZoneResp <span class="cov0" title="0">{
        // 从配置中获取可用区配置
        if zones := h.getZonesFromConfig(region); len(zones) &gt; 0 </span><span class="cov0" title="0">{
                return zones
        }</span>

        // 使用智能生成规则
        <span class="cov0" title="0">return h.generateSmartZones(region)</span>
}

// getZonesFromConfig 从配置中获取可用区
func (h *HuaweiProviderImpl) getZonesFromConfig(region string) []*model.ZoneResp <span class="cov0" title="0">{
        // 可以从配置文件或环境变量读取可用区配置
        // 这里提供一个扩展点，可以根据实际需求实现

        // 示例：从环境变量读取
        if zoneConfig := os.Getenv("HUAWEI_CLOUD_ZONES_" + strings.ToUpper(strings.ReplaceAll(region, "-", "_"))); zoneConfig != "" </span><span class="cov0" title="0">{
                zoneIDs := strings.Split(zoneConfig, ",")
                var zones []*model.ZoneResp
                for _, zoneID := range zoneIDs </span><span class="cov0" title="0">{
                        zoneID = strings.TrimSpace(zoneID)
                        if zoneID != "" </span><span class="cov0" title="0">{
                                zones = append(zones, &amp;model.ZoneResp{
                                        ZoneId:    zoneID,
                                        LocalName: h.generateZoneLocalName(zoneID),
                                })
                        }</span>
                }
                <span class="cov0" title="0">return zones</span>
        }

        <span class="cov0" title="0">return []*model.ZoneResp{}</span>
}

// generateSmartZones 智能生成可用区
func (h *HuaweiProviderImpl) generateSmartZones(region string) []*model.ZoneResp <span class="cov0" title="0">{
        // 基于华为云可用区命名规则智能生成
        // 华为云可用区通常格式为：region-az，如 cn-north-4-01

        var zones []*model.ZoneResp

        // 获取可用区后缀
        zoneSuffixes := h.getZoneSuffixes()

        for _, suffix := range zoneSuffixes </span><span class="cov0" title="0">{
                zoneID := fmt.Sprintf("%s-%s", region, suffix)
                zones = append(zones, &amp;model.ZoneResp{
                        ZoneId:    zoneID,
                        LocalName: h.generateZoneLocalName(zoneID),
                })
        }</span>

        // 如果生成的可用区为空，使用默认可用区
        <span class="cov0" title="0">if len(zones) == 0 </span><span class="cov0" title="0">{
                zones = h.getDefaultZones(region)
        }</span>

        <span class="cov0" title="0">return zones</span>
}

// getZoneSuffixes 获取可用区后缀
func (h *HuaweiProviderImpl) getZoneSuffixes() []string <span class="cov0" title="0">{
        // 优先从配置中获取
        if zoneSuffixes := h.getZoneSuffixesFromConfig(); len(zoneSuffixes) &gt; 0 </span><span class="cov0" title="0">{
                return zoneSuffixes
        }</span>

        // 从SDK动态获取
        <span class="cov0" title="0">if zoneSuffixes := h.getZoneSuffixesFromSDK(); len(zoneSuffixes) &gt; 0 </span><span class="cov0" title="0">{
                return zoneSuffixes
        }</span>

        // 如果都不可用，返回空数组
        <span class="cov0" title="0">return []string{}</span>
}

// getZoneSuffixesFromConfig 从配置中获取可用区后缀
func (h *HuaweiProviderImpl) getZoneSuffixesFromConfig() []string <span class="cov0" title="0">{
        // 从环境变量读取
        if zoneSuffixes := os.Getenv("HUAWEI_CLOUD_ZONE_SUFFIXES"); zoneSuffixes != "" </span><span class="cov0" title="0">{
                return strings.Split(zoneSuffixes, ",")
        }</span>
        <span class="cov0" title="0">return []string{}</span>
}

// getZoneSuffixesFromSDK 从SDK动态获取可用区后缀
func (h *HuaweiProviderImpl) getZoneSuffixesFromSDK() []string <span class="cov0" title="0">{
        // 通过API动态获取可用区后缀
        // 这里可以调用华为云API获取可用区信息
        if h.sdk != nil </span><span class="cov0" title="0">{
                // 尝试通过已知区域推断可用区后缀
                knownRegions := h.getAllRegionsFromSDK()
                suffixSet := make(map[string]struct{})

                for _, region := range knownRegions </span><span class="cov0" title="0">{
                        // 从区域ID中提取可用区后缀
                        if suffix := h.extractZoneSuffixFromRegion(region); suffix != "" </span><span class="cov0" title="0">{
                                suffixSet[suffix] = struct{}{}
                        }</span>
                }

                <span class="cov0" title="0">var suffixes []string
                for suffix := range suffixSet </span><span class="cov0" title="0">{
                        suffixes = append(suffixes, suffix)
                }</span>

                <span class="cov0" title="0">return suffixes</span>
        }

        <span class="cov0" title="0">return []string{}</span>
}

// extractZoneSuffixFromRegion 从区域ID中提取可用区后缀
func (h *HuaweiProviderImpl) extractZoneSuffixFromRegion(regionID string) string <span class="cov0" title="0">{
        // 华为云区域ID格式：region-az，如 cn-north-4-01
        parts := strings.Split(regionID, "-")
        if len(parts) &gt;= 4 </span><span class="cov0" title="0">{
                return parts[len(parts)-1]
        }</span>
        <span class="cov0" title="0">return ""</span>
}

// getDefaultZones 获取默认可用区
func (h *HuaweiProviderImpl) getDefaultZones(region string) []*model.ZoneResp <span class="cov0" title="0">{
        // 优先从SDK动态获取
        if zones := h.getZonesFromSDK(region); len(zones) &gt; 0 </span><span class="cov0" title="0">{
                return zones
        }</span>

        // 从配置中获取
        <span class="cov0" title="0">if zones := h.getZonesFromConfig(region); len(zones) &gt; 0 </span><span class="cov0" title="0">{
                return zones
        }</span>

        // 如果都不可用，返回空数组
        <span class="cov0" title="0">return []*model.ZoneResp{}</span>
}

// getZonesFromSDK 从SDK动态获取可用区
func (h *HuaweiProviderImpl) getZonesFromSDK(region string) []*model.ZoneResp <span class="cov0" title="0">{
        // 通过API动态获取可用区
        if h.sdk != nil </span><span class="cov0" title="0">{
                // 尝试通过ECS API获取可用区信息
                if zones, err := h.getZonesFromAPI(region); err == nil &amp;&amp; len(zones) &gt; 0 </span><span class="cov0" title="0">{
                        return zones
                }</span>
        }
        <span class="cov0" title="0">return []*model.ZoneResp{}</span>
}

// getDefaultInstanceTypes 获取默认实例类型列表
func (h *HuaweiProviderImpl) getDefaultInstanceTypes() []*model.InstanceTypeResp <span class="cov0" title="0">{
        // 优先从SDK动态获取
        if instanceTypes := h.getInstanceTypesFromSDK(); len(instanceTypes) &gt; 0 </span><span class="cov0" title="0">{
                return instanceTypes
        }</span>

        // 从配置中获取
        <span class="cov0" title="0">if instanceTypes := h.getInstanceTypesFromConfig(""); len(instanceTypes) &gt; 0 </span><span class="cov0" title="0">{
                return instanceTypes
        }</span>

        // 如果都不可用，返回空数组
        <span class="cov0" title="0">return []*model.InstanceTypeResp{}</span>
}

// getInstanceTypesFromSDK 从SDK动态获取实例类型
func (h *HuaweiProviderImpl) getInstanceTypesFromSDK() []*model.InstanceTypeResp <span class="cov0" title="0">{
        // 通过API动态获取实例类型
        if h.sdk != nil </span><span class="cov0" title="0">{
                // 尝试通过ECS API获取实例类型信息
                // 这里可以调用华为云ECS的实例类型列表API
                // 由于华为云可能没有直接提供实例类型列表API，我们使用其他方法

                // 方案：通过已知区域获取实例类型
                knownRegions := h.getAllRegionsFromSDK()
                instanceTypeSet := make(map[string]*model.InstanceTypeResp)

                for _, region := range knownRegions </span><span class="cov0" title="0">{
                        if instanceTypes, err := h.getInstanceTypesFromAPI(region); err == nil </span><span class="cov0" title="0">{
                                for _, instanceType := range instanceTypes </span><span class="cov0" title="0">{
                                        instanceTypeSet[instanceType.InstanceTypeId] = instanceType
                                }</span>
                        }
                }

                <span class="cov0" title="0">var instanceTypes []*model.InstanceTypeResp
                for _, instanceType := range instanceTypeSet </span><span class="cov0" title="0">{
                        instanceTypes = append(instanceTypes, instanceType)
                }</span>

                <span class="cov0" title="0">return instanceTypes</span>
        }

        <span class="cov0" title="0">return []*model.InstanceTypeResp{}</span>
}

// getDefaultImages 获取默认镜像列表
func (h *HuaweiProviderImpl) getDefaultImages() []*model.ImageResp <span class="cov0" title="0">{
        // 优先从SDK动态获取
        if images := h.getImagesFromSDK(); len(images) &gt; 0 </span><span class="cov0" title="0">{
                return images
        }</span>

        // 从配置中获取
        <span class="cov0" title="0">if images := h.getImagesFromConfig(""); len(images) &gt; 0 </span><span class="cov0" title="0">{
                return images
        }</span>

        // 如果都不可用，返回空数组
        <span class="cov0" title="0">return []*model.ImageResp{}</span>
}

// getImagesFromSDK 从SDK动态获取镜像
func (h *HuaweiProviderImpl) getImagesFromSDK() []*model.ImageResp <span class="cov0" title="0">{
        // 通过API动态获取镜像
        if h.sdk != nil </span><span class="cov0" title="0">{
                // 尝试通过ECS API获取镜像信息
                // 这里可以调用华为云ECS的镜像列表API
                // 由于华为云可能没有直接提供镜像列表API，我们使用其他方法

                // 方案：通过已知区域获取镜像
                knownRegions := h.getAllRegionsFromSDK()
                imageSet := make(map[string]*model.ImageResp)

                for _, region := range knownRegions </span><span class="cov0" title="0">{
                        if images, err := h.getImagesFromAPI(region); err == nil </span><span class="cov0" title="0">{
                                for _, image := range images </span><span class="cov0" title="0">{
                                        imageSet[image.ImageId] = image
                                }</span>
                        }
                }

                <span class="cov0" title="0">var images []*model.ImageResp
                for _, image := range imageSet </span><span class="cov0" title="0">{
                        images = append(images, image)
                }</span>

                <span class="cov0" title="0">return images</span>
        }

        <span class="cov0" title="0">return []*model.ImageResp{}</span>
}

// getAvailableInstanceTypes 获取实例类型列表
func (h *HuaweiProviderImpl) getAvailableInstanceTypes(region string) []*model.InstanceTypeResp <span class="cov0" title="0">{
        // 优先尝试通过API动态获取实例类型
        if instanceTypes, err := h.getInstanceTypesFromAPI(region); err == nil &amp;&amp; len(instanceTypes) &gt; 0 </span><span class="cov0" title="0">{
                return instanceTypes
        }</span>

        // 如果API获取失败，使用配置或默认值
        <span class="cov0" title="0">return h.getInstanceTypesFromConfig(region)</span>
}

// getInstanceTypesFromAPI 通过API获取实例类型列表
func (h *HuaweiProviderImpl) getInstanceTypesFromAPI(region string) ([]*model.InstanceTypeResp, error) <span class="cov0" title="0">{
        // 检查SDK服务是否已初始化
        if h.ecsService == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("ECS服务未初始化")
        }</span>

        <span class="cov0" title="0">ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        defer cancel()

        // 尝试通过ECS API获取实例类型列表
        // 这里可以调用华为云ECS的实例类型列表API
        // 由于华为云可能没有直接提供实例类型列表API，我们使用其他方法

        // 方案1：通过实例列表推断实例类型
        instances, _, err := h.ListInstances(ctx, region, 1, 100)
        if err == nil &amp;&amp; len(instances) &gt; 0 </span><span class="cov0" title="0">{
                instanceTypeMap := make(map[string]*model.InstanceTypeResp)
                for _, instance := range instances </span><span class="cov0" title="0">{
                        if instance.InstanceType != "" </span><span class="cov0" title="0">{
                                // 解析实例类型信息
                                if instanceType := h.parseInstanceType(instance.InstanceType, instance.Cpu, instance.Memory); instanceType != nil </span><span class="cov0" title="0">{
                                        instanceTypeMap[instance.InstanceType] = instanceType
                                }</span>
                        }
                }

                <span class="cov0" title="0">var instanceTypes []*model.InstanceTypeResp
                for _, instanceType := range instanceTypeMap </span><span class="cov0" title="0">{
                        instanceTypes = append(instanceTypes, instanceType)
                }</span>

                <span class="cov0" title="0">if len(instanceTypes) &gt; 0 </span><span class="cov0" title="0">{
                        return instanceTypes, nil
                }</span>
        }

        <span class="cov0" title="0">return nil, fmt.Errorf("无法通过API获取实例类型列表")</span>
}

// parseInstanceType 解析实例类型信息
func (h *HuaweiProviderImpl) parseInstanceType(instanceTypeID string, cpu, memory int) *model.InstanceTypeResp <span class="cov0" title="0">{
        // 基于华为云实例类型命名规则解析
        // 华为云实例类型格式：{family}.{size}.{version}
        // 例如：c6.large.2, m6.xlarge.2

        parts := strings.Split(instanceTypeID, ".")
        if len(parts) &lt; 2 </span><span class="cov0" title="0">{
                return nil
        }</span>

        <span class="cov0" title="0">family := parts[0]
        size := parts[1]

        // 生成描述
        description := h.generateInstanceTypeDescription(family, size, cpu, memory)

        return &amp;model.InstanceTypeResp{
                InstanceTypeId: instanceTypeID,
                CpuCoreCount:   cpu,
                MemorySize:     memory,
                Description:    description,
        }</span>
}

// generateInstanceTypeDescription 生成实例类型描述
func (h *HuaweiProviderImpl) generateInstanceTypeDescription(family, size string, cpu, memory int) string <span class="cov0" title="0">{
        familyNames := map[string]string{
                "c": "通用型",
                "m": "内存优化型",
                "s": "通用型",
                "d": "存储优化型",
                "g": "GPU型",
                "f": "FPGA型",
                "h": "高性能计算型",
        }

        familyName := familyNames[family]
        if familyName == "" </span><span class="cov0" title="0">{
                familyName = "通用型"
        }</span>

        <span class="cov0" title="0">return fmt.Sprintf("%s %s.%s (%d核%dGB)", familyName, family, size, cpu, memory)</span>
}

// getInstanceTypesFromConfig 从配置中获取实例类型
func (h *HuaweiProviderImpl) getInstanceTypesFromConfig(region string) []*model.InstanceTypeResp <span class="cov0" title="0">{
        // 可以从配置文件或环境变量读取实例类型配置
        // 这里提供一个扩展点，可以根据实际需求实现

        // 示例：从环境变量读取
        if instanceTypeConfig := os.Getenv("HUAWEI_CLOUD_INSTANCE_TYPES_" + strings.ToUpper(strings.ReplaceAll(region, "-", "_"))); instanceTypeConfig != "" </span><span class="cov0" title="0">{
                instanceTypeIDs := strings.Split(instanceTypeConfig, ",")
                var instanceTypes []*model.InstanceTypeResp
                for _, instanceTypeID := range instanceTypeIDs </span><span class="cov0" title="0">{
                        instanceTypeID = strings.TrimSpace(instanceTypeID)
                        if instanceTypeID != "" </span><span class="cov0" title="0">{
                                // 解析实例类型ID
                                if instanceType := h.parseInstanceType(instanceTypeID, 0, 0); instanceType != nil </span><span class="cov0" title="0">{
                                        instanceTypes = append(instanceTypes, instanceType)
                                }</span>
                        }
                }
                <span class="cov0" title="0">return instanceTypes</span>
        }

        // 返回默认实例类型列表
        <span class="cov0" title="0">return h.getDefaultInstanceTypes()</span>
}

// getAvailableImages 获取镜像列表
func (h *HuaweiProviderImpl) getAvailableImages(region string) []*model.ImageResp <span class="cov0" title="0">{
        // 优先尝试通过API动态获取镜像
        if images, err := h.getImagesFromAPI(region); err == nil &amp;&amp; len(images) &gt; 0 </span><span class="cov0" title="0">{
                return images
        }</span>

        // 如果API获取失败，使用配置或默认值
        <span class="cov0" title="0">return h.getImagesFromConfig(region)</span>
}

// getImagesFromAPI 通过API获取镜像列表
func (h *HuaweiProviderImpl) getImagesFromAPI(region string) ([]*model.ImageResp, error) <span class="cov0" title="0">{
        // 检查SDK服务是否已初始化
        if h.ecsService == nil </span><span class="cov0" title="0">{
                return nil, fmt.Errorf("ECS服务未初始化")
        }</span>

        <span class="cov0" title="0">ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        defer cancel()

        // 尝试通过ECS API获取镜像列表
        // 这里可以调用华为云ECS的镜像列表API
        // 由于华为云可能没有直接提供镜像列表API，我们使用其他方法

        // 方案1：通过实例列表推断镜像
        instances, _, err := h.ListInstances(ctx, region, 1, 100)
        if err == nil &amp;&amp; len(instances) &gt; 0 </span><span class="cov0" title="0">{
                imageMap := make(map[string]*model.ImageResp)
                for _, instance := range instances </span><span class="cov0" title="0">{
                        if instance.ImageId != "" </span><span class="cov0" title="0">{
                                // 解析镜像信息
                                if image := h.parseImage(instance.ImageId, instance.InstanceName); image != nil </span><span class="cov0" title="0">{
                                        imageMap[instance.ImageId] = image
                                }</span>
                        }
                }

                <span class="cov0" title="0">var images []*model.ImageResp
                for _, image := range imageMap </span><span class="cov0" title="0">{
                        images = append(images, image)
                }</span>

                <span class="cov0" title="0">if len(images) &gt; 0 </span><span class="cov0" title="0">{
                        return images, nil
                }</span>
        }

        <span class="cov0" title="0">return nil, fmt.Errorf("无法通过API获取镜像列表")</span>
}

// parseImage 解析镜像信息
func (h *HuaweiProviderImpl) parseImage(imageID, instanceName string) *model.ImageResp <span class="cov0" title="0">{
        // 基于华为云镜像命名规则解析
        // 华为云镜像通常包含操作系统信息

        // 推断操作系统类型
        osType := h.inferOSType(imageID, instanceName)
        osName := h.inferOSName(imageID, instanceName)

        return &amp;model.ImageResp{
                ImageId:     imageID,
                ImageName:   osName,
                OSType:      osType,
                Description: fmt.Sprintf("%s 镜像", osName),
        }
}</span>

// inferOSType 推断操作系统类型
func (h *HuaweiProviderImpl) inferOSType(imageID, instanceName string) string <span class="cov0" title="0">{
        // 基于镜像ID或实例名称推断操作系统类型
        lowerImageID := strings.ToLower(imageID)
        lowerInstanceName := strings.ToLower(instanceName)

        if strings.Contains(lowerImageID, "windows") || strings.Contains(lowerInstanceName, "windows") </span><span class="cov0" title="0">{
                return "Windows"
        }</span>

        <span class="cov0" title="0">if strings.Contains(lowerImageID, "centos") || strings.Contains(lowerInstanceName, "centos") </span><span class="cov0" title="0">{
                return "Linux"
        }</span>

        <span class="cov0" title="0">if strings.Contains(lowerImageID, "ubuntu") || strings.Contains(lowerInstanceName, "ubuntu") </span><span class="cov0" title="0">{
                return "Linux"
        }</span>

        <span class="cov0" title="0">if strings.Contains(lowerImageID, "debian") || strings.Contains(lowerInstanceName, "debian") </span><span class="cov0" title="0">{
                return "Linux"
        }</span>

        // 默认返回Linux
        <span class="cov0" title="0">return "Linux"</span>
}

// inferOSName 推断操作系统名称
func (h *HuaweiProviderImpl) inferOSName(imageID, instanceName string) string <span class="cov0" title="0">{
        // 基于镜像ID或实例名称推断操作系统名称
        lowerImageID := strings.ToLower(imageID)
        lowerInstanceName := strings.ToLower(instanceName)

        if strings.Contains(lowerImageID, "centos") || strings.Contains(lowerInstanceName, "centos") </span><span class="cov0" title="0">{
                return "CentOS"
        }</span>

        <span class="cov0" title="0">if strings.Contains(lowerImageID, "ubuntu") || strings.Contains(lowerInstanceName, "ubuntu") </span><span class="cov0" title="0">{
                return "Ubuntu"
        }</span>

        <span class="cov0" title="0">if strings.Contains(lowerImageID, "debian") || strings.Contains(lowerInstanceName, "debian") </span><span class="cov0" title="0">{
                return "Debian"
        }</span>

        <span class="cov0" title="0">if strings.Contains(lowerImageID, "windows") || strings.Contains(lowerInstanceName, "windows") </span><span class="cov0" title="0">{
                return "Windows Server"
        }</span>

        // 默认返回通用名称
        <span class="cov0" title="0">return "通用镜像"</span>
}

// getImagesFromConfig 从配置中获取镜像
func (h *HuaweiProviderImpl) getImagesFromConfig(region string) []*model.ImageResp <span class="cov0" title="0">{
        // 可以从配置文件或环境变量读取镜像配置
        // 这里提供一个扩展点，可以根据实际需求实现

        // 示例：从环境变量读取
        if imageConfig := os.Getenv("HUAWEI_CLOUD_IMAGES_" + strings.ToUpper(strings.ReplaceAll(region, "-", "_"))); imageConfig != "" </span><span class="cov0" title="0">{
                imageIDs := strings.Split(imageConfig, ",")
                var images []*model.ImageResp
                for _, imageID := range imageIDs </span><span class="cov0" title="0">{
                        imageID = strings.TrimSpace(imageID)
                        if imageID != "" </span><span class="cov0" title="0">{
                                // 解析镜像ID
                                if image := h.parseImage(imageID, ""); image != nil </span><span class="cov0" title="0">{
                                        images = append(images, image)
                                }</span>
                        }
                }
                <span class="cov0" title="0">return images</span>
        }

        // 返回默认镜像列表
        <span class="cov0" title="0">return []*model.ImageResp{}</span>
}

// getDiskTypeDescription 获取磁盘类型描述
func (h *HuaweiProviderImpl) getDiskTypeDescription(diskType string) string <span class="cov0" title="0">{
        // 优先从配置中获取磁盘类型描述
        if description := h.getDiskTypeDescriptionFromConfig(diskType); description != "" </span><span class="cov0" title="0">{
                return description
        }</span>

        // 如果配置中没有，使用默认映射
        <span class="cov0" title="0">return h.getDefaultDiskTypeDescription(diskType)</span>
}

// getDiskTypeDescriptionFromConfig 从配置中获取磁盘类型描述
func (h *HuaweiProviderImpl) getDiskTypeDescriptionFromConfig(diskType string) string <span class="cov0" title="0">{
        // 可以从配置文件或环境变量读取磁盘类型描述配置
        // 这里提供一个扩展点，可以根据实际需求实现

        // 示例：从环境变量读取
        envKey := "HUAWEI_CLOUD_DISK_TYPE_" + strings.ToUpper(diskType)
        if description := os.Getenv(envKey); description != "" </span><span class="cov0" title="0">{
                return description
        }</span>

        // 示例：从环境变量读取所有磁盘类型映射
        <span class="cov0" title="0">if diskTypeMapping := os.Getenv("HUAWEI_CLOUD_DISK_TYPE_MAPPING"); diskTypeMapping != "" </span><span class="cov0" title="0">{
                mappings := strings.Split(diskTypeMapping, ",")
                for _, mapping := range mappings </span><span class="cov0" title="0">{
                        parts := strings.Split(mapping, "=")
                        if len(parts) == 2 &amp;&amp; strings.TrimSpace(parts[0]) == diskType </span><span class="cov0" title="0">{
                                return strings.TrimSpace(parts[1])
                        }</span>
                }
        }

        <span class="cov0" title="0">return ""</span>
}

// getDefaultDiskTypeDescription 获取默认磁盘类型描述
func (h *HuaweiProviderImpl) getDefaultDiskTypeDescription(diskType string) string <span class="cov0" title="0">{
        descriptions := map[string]string{
                "SSD":    "超高IO云硬盘",
                "GPSSD":  "通用型SSD云硬盘",
                "SAS":    "高IO云硬盘",
                "SATA":   "普通IO云硬盘",
                "ESSD":   "极速IO云硬盘",
                "GPSSD2": "通用型SSD V2云硬盘",
                "ESSD2":  "极速IO V2云硬盘",
                "SSD2":   "超高IO V2云硬盘",
                "SAS2":   "高IO V2云硬盘",
                "SATA2":  "普通IO V2云硬盘",
        }

        if desc, exists := descriptions[diskType]; exists </span><span class="cov0" title="0">{
                return desc
        }</span>

        // 如果找不到描述，尝试智能推断
        <span class="cov0" title="0">return h.inferDiskTypeDescription(diskType)</span>
}

// inferDiskTypeDescription 智能推断磁盘类型描述
func (h *HuaweiProviderImpl) inferDiskTypeDescription(diskType string) string <span class="cov0" title="0">{
        // 基于磁盘类型名称智能推断描述
        lowerDiskType := strings.ToLower(diskType)

        if strings.Contains(lowerDiskType, "ssd") </span><span class="cov0" title="0">{
                if strings.Contains(lowerDiskType, "gp") </span><span class="cov0" title="0">{
                        return "通用型SSD云硬盘"
                }</span>
                <span class="cov0" title="0">if strings.Contains(lowerDiskType, "es") </span><span class="cov0" title="0">{
                        return "极速IO云硬盘"
                }</span>
                <span class="cov0" title="0">return "超高IO云硬盘"</span>
        }

        <span class="cov0" title="0">if strings.Contains(lowerDiskType, "sas") </span><span class="cov0" title="0">{
                return "高IO云硬盘"
        }</span>

        <span class="cov0" title="0">if strings.Contains(lowerDiskType, "sata") </span><span class="cov0" title="0">{
                return "普通IO云硬盘"
        }</span>

        // 默认返回磁盘类型本身
        <span class="cov0" title="0">return diskType</span>
}

// 转换函数
func (h *HuaweiProviderImpl) convertToResourceEcsFromListInstance(instance ecsmodel.ServerDetail) *model.ResourceEcs <span class="cov8" title="1">{
        lastSyncTime := time.Now()

        // 提取安全组ID列表
        var securityGroupIds []string
        if instance.SecurityGroups != nil </span><span class="cov0" title="0">{
                for _, sg := range instance.SecurityGroups </span><span class="cov0" title="0">{
                        securityGroupIds = append(securityGroupIds, sg.Id)
                }</span>
        }

        // 提取IP地址信息
        <span class="cov8" title="1">var privateIPs []string
        var publicIPs []string
        if instance.Addresses != nil </span><span class="cov0" title="0">{
                for networkName, addresses := range instance.Addresses </span><span class="cov0" title="0">{
                        for _, addr := range addresses </span><span class="cov0" title="0">{
                                // 根据IP类型分类
                                if addr.OSEXTIPStype != nil </span><span class="cov0" title="0">{
                                        switch *addr.OSEXTIPStype </span>{
                                        case ecsmodel.GetServerAddressOSEXTIPStypeEnum().FIXED:<span class="cov0" title="0">
                                                privateIPs = append(privateIPs, addr.Addr)</span>
                                        case ecsmodel.GetServerAddressOSEXTIPStypeEnum().FLOATING:<span class="cov0" title="0">
                                                publicIPs = append(publicIPs, addr.Addr)</span>
                                        }
                                } else<span class="cov0" title="0"> {
                                        // 如果没有明确类型，根据网络名称判断
                                        if networkName == "external" || networkName == "public" </span><span class="cov0" title="0">{
                                                publicIPs = append(publicIPs, addr.Addr)
                                        }</span> else<span class="cov0" title="0"> {
                                                privateIPs = append(privateIPs, addr.Addr)
                                        }</span>
                                }
                        }
                }
        }

        // 提取标签信息
        <span class="cov8" title="1">var tags []string
        if instance.Tags != nil </span><span class="cov0" title="0">{
                for _, tag := range *instance.Tags </span><span class="cov0" title="0">{
                        tags = append(tags, tag)
                }</span>
        }

        // 提取VPC ID
        <span class="cov8" title="1">var vpcId string
        if instance.Metadata != nil </span><span class="cov0" title="0">{
                if vpc, ok := instance.Metadata["vpc_id"]; ok </span><span class="cov0" title="0">{
                        vpcId = vpc
                }</span>
        }

        // 提取区域ID（从可用区推断）
        <span class="cov8" title="1">regionId := ""
        if instance.OSEXTAZavailabilityZone != "" </span><span class="cov0" title="0">{
                // 华为云的可用区格式通常是 region-az，如 cn-north-4-01
                // 提取区域部分
                if len(instance.OSEXTAZavailabilityZone) &gt;= 2 </span><span class="cov0" title="0">{
                        parts := strings.Split(instance.OSEXTAZavailabilityZone, "-")
                        if len(parts) &gt;= 3 </span><span class="cov0" title="0">{
                                regionId = strings.Join(parts[:len(parts)-1], "-")
                        }</span>
                }
        }

        // 提取CPU和内存信息
        <span class="cov8" title="1">var cpu int
        var memory int
        if instance.Flavor != nil </span><span class="cov0" title="0">{
                if vcpus, err := strconv.Atoi(instance.Flavor.Vcpus); err == nil </span><span class="cov0" title="0">{
                        cpu = vcpus
                }</span>
                <span class="cov0" title="0">if ram, err := strconv.Atoi(instance.Flavor.Ram); err == nil </span><span class="cov0" title="0">{
                        // 华为云返回的是MB，转换为GB
                        memory = ram / 1024
                        if memory == 0 &amp;&amp; ram &gt; 0 </span><span class="cov0" title="0">{
                                memory = 1 // 如果小于1GB但大于0，设为1GB
                        }</span>
                }
        }

        // 提取镜像ID
        <span class="cov8" title="1">var imageId string
        if instance.Image != nil </span><span class="cov0" title="0">{
                imageId = instance.Image.Id
        }</span>

        // 提取实例类型
        <span class="cov8" title="1">instanceType := ""
        if instance.Flavor != nil </span><span class="cov0" title="0">{
                instanceType = instance.Flavor.Name
        }</span>

        // 提取主机名
        <span class="cov8" title="1">hostName := instance.OSEXTSRVATTRhostname

        // 处理描述字段
        description := ""
        if instance.Description != nil </span><span class="cov0" title="0">{
                description = *instance.Description
        }</span>

        // 提取计费类型
        <span class="cov8" title="1">instanceChargeType := "PostPaid" // 默认按需付费
        if instance.Metadata != nil </span><span class="cov0" title="0">{
                if chargingMode, ok := instance.Metadata["charging_mode"]; ok </span><span class="cov0" title="0">{
                        switch chargingMode </span>{
                        case "0":<span class="cov0" title="0">
                                instanceChargeType = "PostPaid"</span>
                        case "1":<span class="cov0" title="0">
                                instanceChargeType = "PrePaid"</span>
                        case "2":<span class="cov0" title="0">
                                instanceChargeType = "Spot"</span>
                        }
                }
        }

        <span class="cov8" title="1">return &amp;model.ResourceEcs{
                InstanceName:       instance.Name,
                InstanceId:         instance.Id,
                Provider:           model.CloudProviderHuawei,
                RegionId:           regionId,
                ZoneId:             instance.OSEXTAZavailabilityZone,
                VpcId:              vpcId,
                Status:             instance.Status,
                CreationTime:       instance.Created,
                InstanceChargeType: instanceChargeType,
                Description:        description,
                SecurityGroupIds:   model.StringList(securityGroupIds),
                PrivateIpAddress:   model.StringList(privateIPs),
                PublicIpAddress:    model.StringList(publicIPs),
                LastSyncTime:       &amp;lastSyncTime,
                Tags:               model.StringList(tags),
                Cpu:                cpu,
                Memory:             memory,
                InstanceType:       instanceType,
                ImageId:            imageId,
                HostName:           hostName,
                IpAddr:             h.getFirstIP(privateIPs),
        }</span>
}

func (h *HuaweiProviderImpl) convertToResourceEcsFromInstanceDetail(instance *ecsmodel.ServerDetail) *model.ResourceEcs <span class="cov8" title="1">{
        if instance == nil </span><span class="cov0" title="0">{
                return nil
        }</span>

        // 直接复用列表转换函数的逻辑
        <span class="cov8" title="1">return h.convertToResourceEcsFromListInstance(*instance)</span>
}

func (h *HuaweiProviderImpl) convertToResourceVpcFromListVpc(vpcData vpcmodel.Vpc, region string) *model.ResourceVpc <span class="cov8" title="1">{
        // 提取标签信息
        var tags []string
        if vpcData.Tags != nil </span><span class="cov0" title="0">{
                for _, tag := range vpcData.Tags </span><span class="cov0" title="0">{
                        tags = append(tags, fmt.Sprintf("%s=%s", tag.Key, tag.Value))
                }</span>
        }

        // 提取子网ID列表
        <span class="cov8" title="1">var vSwitchIds []string
        // 通过API获取VPC下的子网列表（仅在VPC服务已初始化时）
        if h.vpcService != nil </span><span class="cov0" title="0">{
                subnets, err := h.getSubnetsByVpc(context.Background(), region, vpcData.Id)
                if err == nil </span><span class="cov0" title="0">{
                        for _, subnet := range subnets </span><span class="cov0" title="0">{
                                if subnet.SubnetId != "" </span><span class="cov0" title="0">{
                                        vSwitchIds = append(vSwitchIds, subnet.SubnetId)
                                }</span>
                        }
                }
        }

        // 处理创建时间
        <span class="cov8" title="1">creationTime := ""
        if vpcData.CreatedAt != nil </span><span class="cov0" title="0">{
                creationTime = vpcData.CreatedAt.String()
        }</span>

        // 判断是否为默认VPC（通常第一个VPC是默认的）
        <span class="cov8" title="1">isDefault := false
        // 通过检查VPC名称或标签来判断是否为默认VPC
        if vpcData.Name == "default" || vpcData.Name == "Default" </span><span class="cov0" title="0">{
                isDefault = true
        }</span>
        // 也可以通过标签判断
        <span class="cov8" title="1">if vpcData.Tags != nil </span><span class="cov0" title="0">{
                for _, tag := range vpcData.Tags </span><span class="cov0" title="0">{
                        if tag.Key == "default" &amp;&amp; tag.Value == "true" </span><span class="cov0" title="0">{
                                isDefault = true
                                break</span>
                        }
                }
        }

        // 提取IPv6 CIDR（华为云VPC可能支持IPv6）
        <span class="cov8" title="1">ipv6CidrBlock := ""
        // 从VPC详情中获取IPv6 CIDR信息
        // 注意：华为云VPC的IPv6字段可能不是CidrV6，需要根据实际SDK字段调整
        // 暂时留空，等待华为云SDK提供IPv6支持

        return &amp;model.ResourceVpc{
                InstanceName:    vpcData.Name,
                InstanceId:      vpcData.Id,
                Provider:        model.CloudProviderHuawei,
                RegionId:        region,
                VpcId:           vpcData.Id,
                Status:          vpcData.Status,
                CreationTime:    creationTime,
                Description:     vpcData.Description,
                LastSyncTime:    time.Now(),
                Tags:            model.StringList(tags),
                VpcName:         vpcData.Name,
                CidrBlock:       vpcData.Cidr,
                Ipv6CidrBlock:   ipv6CidrBlock,
                VSwitchIds:      model.StringList(vSwitchIds),
                IsDefault:       isDefault,
                ResourceGroupId: vpcData.EnterpriseProjectId,
        }</span>
}

func (h *HuaweiProviderImpl) convertToResourceVpcFromDetail(vpcDetail *vpcmodel.Vpc, region string) *model.ResourceVpc <span class="cov8" title="1">{
        if vpcDetail == nil </span><span class="cov0" title="0">{
                return nil
        }</span>

        // 直接复用列表转换函数的逻辑
        <span class="cov8" title="1">return h.convertToResourceVpcFromListVpc(*vpcDetail, region)</span>
}

func (h *HuaweiProviderImpl) convertToResourceSecurityGroupFromList(sg vpcmodel.SecurityGroup, region string) *model.ResourceSecurityGroup <span class="cov8" title="1">{
        // 提取标签信息
        var tags []string
        if sg.Tags != nil </span><span class="cov0" title="0">{
                for _, tag := range sg.Tags </span><span class="cov0" title="0">{
                        tags = append(tags, fmt.Sprintf("%s=%s", tag.Key, tag.Value))
                }</span>
        }

        // 提取VPC ID（从安全组信息中获取）
        <span class="cov8" title="1">vpcId := ""
        // 注意：华为云安全组的VPC ID字段可能不是VpcId，需要根据实际SDK字段调整
        // 暂时留空，等待华为云SDK提供VPC ID字段

        return &amp;model.ResourceSecurityGroup{
                InstanceName:      sg.Name,
                InstanceId:        sg.Id,
                Provider:          model.CloudProviderHuawei,
                RegionId:          region,
                VpcId:             vpcId,
                Description:       sg.Description,
                LastSyncTime:      time.Now(),
                Tags:              model.StringList(tags),
                SecurityGroupName: sg.Name,
        }</span>
}

func (h *HuaweiProviderImpl) convertToResourceSecurityGroupFromDetail(sg *vpcmodel.SecurityGroupInfo, region string) *model.ResourceSecurityGroup <span class="cov8" title="1">{
        if sg == nil </span><span class="cov0" title="0">{
                return nil
        }</span>

        // 提取标签信息
        <span class="cov8" title="1">var tags []string
        if sg.Tags != nil </span><span class="cov0" title="0">{
                for _, tag := range sg.Tags </span><span class="cov0" title="0">{
                        tags = append(tags, fmt.Sprintf("%s=%s", tag.Key, tag.Value))
                }</span>
        }

        // 提取VPC ID（从安全组信息中获取）
        <span class="cov8" title="1">vpcId := ""
        // 注意：华为云安全组的VPC ID字段可能不是VpcId，需要根据实际SDK字段调整
        // 暂时留空，等待华为云SDK提供VPC ID字段

        return &amp;model.ResourceSecurityGroup{
                InstanceName:      sg.Name,
                InstanceId:        sg.Id,
                Provider:          model.CloudProviderHuawei,
                RegionId:          region,
                VpcId:             vpcId,
                Description:       sg.Description,
                LastSyncTime:      time.Now(),
                Tags:              model.StringList(tags),
                SecurityGroupName: sg.Name,
        }</span>
}

func (h *HuaweiProviderImpl) convertToResourceDiskFromList(disk evsmodel.VolumeDetail, region string) *model.ResourceDisk <span class="cov8" title="1">{
        // 提取标签信息
        var tags []string
        if disk.Tags != nil </span><span class="cov0" title="0">{
                for key, value := range disk.Tags </span><span class="cov0" title="0">{
                        tags = append(tags, fmt.Sprintf("%s=%s", key, value))
                }</span>
        }

        // 提取挂载的实例ID
        <span class="cov8" title="1">var instanceID string
        if disk.Attachments != nil &amp;&amp; len(disk.Attachments) &gt; 0 </span><span class="cov0" title="0">{
                // 获取第一个挂载的实例ID
                instanceID = disk.Attachments[0].ServerId
        }</span>

        <span class="cov8" title="1">return &amp;model.ResourceDisk{
                InstanceName: disk.Name,
                InstanceId:   disk.Id,
                Provider:     model.CloudProviderHuawei,
                RegionId:     region,
                ZoneId:       disk.AvailabilityZone,
                Status:       disk.Status,
                CreationTime: disk.CreatedAt,
                Description:  disk.Description,
                LastSyncTime: time.Now(),
                Tags:         model.StringList(tags),
                DiskID:       disk.Id,
                DiskName:     disk.Name,
                Size:         int(disk.Size),
                Category:     disk.VolumeType,
                InstanceID:   instanceID,
        }</span>
}

func (h *HuaweiProviderImpl) convertToResourceDiskFromDetail(disk *evsmodel.VolumeDetail, region string) *model.ResourceDisk <span class="cov8" title="1">{
        if disk == nil </span><span class="cov0" title="0">{
                return nil
        }</span>

        // 直接复用列表转换函数的逻辑
        <span class="cov8" title="1">return h.convertToResourceDiskFromList(*disk, region)</span>
}

// 辅助方法
func (h *HuaweiProviderImpl) getInstanceChargeType(chargeType interface{}) string <span class="cov0" title="0">{
        if chargeType != nil </span><span class="cov0" title="0">{
                if ct, ok := chargeType.(string); ok &amp;&amp; ct != "" </span><span class="cov0" title="0">{
                        return ct
                }</span>
        }
        <span class="cov0" title="0">return h.config.Defaults.InstanceChargeType</span>
}

func getStringValue(s *string) string <span class="cov0" title="0">{
        if s == nil </span><span class="cov0" title="0">{
                return ""
        }</span>
        <span class="cov0" title="0">return *s</span>
}

func getIntValue(i *int32) int <span class="cov0" title="0">{
        if i == nil </span><span class="cov0" title="0">{
                return 0
        }</span>
        <span class="cov0" title="0">return int(*i)</span>
}

func getInt32Value(i *int32) int32 <span class="cov0" title="0">{
        if i == nil </span><span class="cov0" title="0">{
                return 0
        }</span>
        <span class="cov0" title="0">return *i</span>
}

// getFirstIP 获取第一个IP地址
func (h *HuaweiProviderImpl) getFirstIP(ips []string) string <span class="cov8" title="1">{
        if len(ips) &gt; 0 </span><span class="cov0" title="0">{
                return ips[0]
        }</span>
        <span class="cov8" title="1">return ""</span>
}

// UpdateConfig 更新配置
func (h *HuaweiProviderImpl) UpdateConfig(config *HuaweiCloudConfig) error <span class="cov0" title="0">{
        if config == nil </span><span class="cov0" title="0">{
                return fmt.Errorf("配置不能为空")
        }</span>

        // 验证配置的合理性
        <span class="cov0" title="0">if err := h.validateConfig(config); err != nil </span><span class="cov0" title="0">{
                return fmt.Errorf("配置验证失败: %w", err)
        }</span>

        <span class="cov0" title="0">h.config = config
        h.logger.Info("华为云配置更新成功")
        return nil</span>
}

// validateConfig 验证配置的合理性
func (h *HuaweiProviderImpl) validateConfig(config *HuaweiCloudConfig) error <span class="cov0" title="0">{
        // 验证默认配置
        if config.Defaults.PageSize &lt;= 0 || config.Defaults.PageSize &gt; 1000 </span><span class="cov0" title="0">{
                return fmt.Errorf("分页大小必须在1-1000之间")
        }</span>

        <span class="cov0" title="0">if config.Defaults.MaxRetries &lt; 0 || config.Defaults.MaxRetries &gt; 10 </span><span class="cov0" title="0">{
                return fmt.Errorf("重试次数必须在0-10之间")
        }</span>

        <span class="cov0" title="0">if config.Defaults.TimeoutSeconds &lt;= 0 || config.Defaults.TimeoutSeconds &gt; 3600 </span><span class="cov0" title="0">{
                return fmt.Errorf("超时时间必须在1-3600秒之间")
        }</span>

        // 验证端点配置
        <span class="cov0" title="0">if config.Endpoints.ECSTemplate == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("ECS端点模板不能为空")
        }</span>

        <span class="cov0" title="0">if config.Endpoints.VPCTemplate == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("VPC端点模板不能为空")
        }</span>

        // 验证发现配置
        <span class="cov0" title="0">if config.Discovery.CacheTimeout &lt;= 0 </span><span class="cov0" title="0">{
                return fmt.Errorf("缓存超时时间必须大于0")
        }</span>

        <span class="cov0" title="0">if config.Discovery.ProbeTimeout &lt;= 0 </span><span class="cov0" title="0">{
                return fmt.Errorf("探测超时时间必须大于0")
        }</span>

        <span class="cov0" title="0">if config.Discovery.MaxConcurrent &lt;= 0 || config.Discovery.MaxConcurrent &gt; 100 </span><span class="cov0" title="0">{
                return fmt.Errorf("最大并发数必须在1-100之间")
        }</span>

        <span class="cov0" title="0">return nil</span>
}

// GetConfig 获取当前配置
func (h *HuaweiProviderImpl) GetConfig() *HuaweiCloudConfig <span class="cov8" title="1">{
        return h.config
}</span>

// EnableRegion 启用指定区域
func (h *HuaweiProviderImpl) EnableRegion(regionID string) error <span class="cov0" title="0">{
        if regionID == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("区域ID不能为空")
        }</span>

        <span class="cov0" title="0">if regionConfig, exists := h.config.Regions[regionID]; exists </span><span class="cov0" title="0">{
                regionConfig.Enabled = true
                h.config.Regions[regionID] = regionConfig
                h.logger.Info("区域已启用", zap.String("regionId", regionID))
                return nil
        }</span>

        <span class="cov0" title="0">return fmt.Errorf("区域 %s 不存在", regionID)</span>
}

// DisableRegion 禁用指定区域
func (h *HuaweiProviderImpl) DisableRegion(regionID string) error <span class="cov0" title="0">{
        if regionID == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("区域ID不能为空")
        }</span>

        <span class="cov0" title="0">if regionConfig, exists := h.config.Regions[regionID]; exists </span><span class="cov0" title="0">{
                regionConfig.Enabled = false
                h.config.Regions[regionID] = regionConfig
                h.logger.Info("区域已禁用", zap.String("regionId", regionID))
                return nil
        }</span>

        <span class="cov0" title="0">return fmt.Errorf("区域 %s 不存在", regionID)</span>
}

// SetCustomEndpoint 设置自定义端点
func (h *HuaweiProviderImpl) SetCustomEndpoint(service, endpoint string) error <span class="cov0" title="0">{
        if service == "" || endpoint == "" </span><span class="cov0" title="0">{
                return fmt.Errorf("服务名和端点不能为空")
        }</span>

        <span class="cov0" title="0">if h.config.Endpoints.CustomEndpoints == nil </span><span class="cov0" title="0">{
                h.config.Endpoints.CustomEndpoints = make(map[string]string)
        }</span>

        <span class="cov0" title="0">h.config.Endpoints.CustomEndpoints[service] = endpoint
        h.logger.Info("自定义端点已设置", zap.String("service", service), zap.String("endpoint", endpoint))
        return nil</span>
}

// GetServiceEndpoint 获取服务端点
func (h *HuaweiProviderImpl) GetServiceEndpoint(service, region string) (string, error) <span class="cov0" title="0">{
        if service == "" || region == "" </span><span class="cov0" title="0">{
                return "", fmt.Errorf("服务名和区域不能为空")
        }</span>

        // 优先使用自定义端点
        <span class="cov0" title="0">if customEndpoint, exists := h.config.Endpoints.CustomEndpoints[service]; exists </span><span class="cov0" title="0">{
                return customEndpoint, nil
        }</span>

        // 使用模板生成端点
        <span class="cov0" title="0">var template string
        switch service </span>{
        case "ecs":<span class="cov0" title="0">
                template = h.config.Endpoints.ECSTemplate</span>
        case "vpc":<span class="cov0" title="0">
                template = h.config.Endpoints.VPCTemplate</span>
        case "evs":<span class="cov0" title="0">
                template = h.config.Endpoints.EVSTemplate</span>
        case "iam":<span class="cov0" title="0">
                template = h.config.Endpoints.IAMTemplate</span>
        default:<span class="cov0" title="0">
                return "", fmt.Errorf("不支持的服务: %s", service)</span>
        }

        <span class="cov0" title="0">if template == "" </span><span class="cov0" title="0">{
                return "", fmt.Errorf("服务 %s 的端点模板未配置", service)
        }</span>

        <span class="cov0" title="0">return fmt.Sprintf(template, region), nil</span>
}

// ResetToDefaults 重置为默认配置
func (h *HuaweiProviderImpl) ResetToDefaults() <span class="cov8" title="1">{
        h.config = getDefaultHuaweiConfig()
        h.logger.Info("配置已重置为默认值")
}</span>

// ExportConfig 导出配置（用于持久化）
func (h *HuaweiProviderImpl) ExportConfig() ([]byte, error) <span class="cov8" title="1">{
        return json.Marshal(h.config)
}</span>

// ImportConfig 导入配置（从持久化存储加载）
func (h *HuaweiProviderImpl) ImportConfig(data []byte) error <span class="cov0" title="0">{
        var config HuaweiCloudConfig
        if err := json.Unmarshal(data, &amp;config); err != nil </span><span class="cov0" title="0">{
                return fmt.Errorf("配置解析失败: %w", err)
        }</span>

        <span class="cov0" title="0">if err := h.validateConfig(&amp;config); err != nil </span><span class="cov0" title="0">{
                return fmt.Errorf("配置验证失败: %w", err)
        }</span>

        <span class="cov0" title="0">h.config = &amp;config
        h.logger.Info("配置导入成功")
        return nil</span>
}
</pre>
		
		</div>
	</body>
	<script>
	(function() {
		var files = document.getElementById('files');
		var visible;
		files.addEventListener('change', onChange, false);
		function select(part) {
			if (visible)
				visible.style.display = 'none';
			visible = document.getElementById(part);
			if (!visible)
				return;
			files.value = part;
			visible.style.display = 'block';
			location.hash = part;
		}
		function onChange() {
			select(files.value);
			window.scrollTo(0, 0);
		}
		if (location.hash != "") {
			select(location.hash.substr(1));
		}
		if (!visible) {
			select("file0");
		}
	})();
	</script>
</html>
